diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 4520fbe352cea..8b9fae732c1f5 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -89,6 +89,7 @@ pub(crate) fn provide(providers: &mut Providers) { opaque_ty_origin, rendered_precise_capturing_args, const_param_default, + anon_const_kind, ..*providers }; } @@ -1828,3 +1829,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, + } +} diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 2bed28d7b710c..7eb896f0bf149 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -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` 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::]`. + // + // 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`. + 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`. - 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, + 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) } + // Default to no generic parameters for other kinds of anon consts + ty::AnonConstKind::NonTypeSystem => None, } } Node::ConstBlock(_) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 76bae39ef8c00..9b369ce26ca44 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -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) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7ac72ef814a9c..3ab989d2d3ba7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -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) { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index c86cf567283fe..929fc6825382c 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -480,6 +480,7 @@ define_tables! { doc_link_traits_in_scope: Table>, assumed_wf_types_for_rpitit: Table, Span)>>, opaque_ty_origin: Table>>, + anon_const_kind: Table>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 5bd111fa2f22d..fef1db8799c49 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -311,6 +311,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, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index eb04c354c773b..3576033b9cd66 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2586,6 +2586,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! } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index dc5fe2d8f8b06..455ac66041261 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -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, +} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c4ddaca26b229..2e6ab2f8cf2df 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -73,8 +73,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, diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index ecd6132b3ef35..3858778bfc8fb 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -68,6 +68,7 @@ trivially_parameterized_over_tcx! { ty::AsyncDestructor, ty::AssocItemContainer, ty::Asyncness, + ty::AnonConstKind, ty::DeducedParamAttrs, ty::Destructor, ty::Generics, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 5b938456e03b0..d12fe02baa1f2 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -542,10 +542,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). @@ -553,65 +556,89 @@ 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) + } } + } else { + let typing_env = infcx + .typing_env(tcx.erase_regions(param_env)) + .with_post_analysis_normalized(tcx); + (uv.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) + } + 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"); } + + // 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 + 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) } - } 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", - ); - - 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) }; - 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( diff --git a/tests/crashes/133199.rs b/tests/crashes/133199.rs deleted file mode 100644 index 76535fa83a6d0..0000000000000 --- a/tests/crashes/133199.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #133199 -//@ aux-build: aux133199.rs - -extern crate aux133199; - -use aux133199::FixedBitSet; - -fn main() { - FixedBitSet::<7>::new(); - //~^ ERROR -} diff --git a/tests/crashes/136894.rs b/tests/crashes/136894.rs deleted file mode 100644 index 26bbb78717e1b..0000000000000 --- a/tests/crashes/136894.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #136894 -#![feature(generic_const_exprs)] -#![crate_type = "lib"] -#![allow(incomplete_features, dead_code)] - -struct X([(); f::()]) where [(); f::()]:; - -const fn f() -> usize { panic!() } diff --git a/tests/crashes/137813.rs b/tests/crashes/137813.rs deleted file mode 100644 index 5d205ee533122..0000000000000 --- a/tests/crashes/137813.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: #137813 -trait AssocConst { - const A: u8; -} - -impl AssocConst for (T,) { - const A: u8 = 0; -} - -trait Trait {} - -impl Trait for () where (U,): AssocConst {} - -fn foo() -where - (): Trait, -{ -} diff --git a/tests/ui/const-generics/associated_const_equality/equality_bound_with_infer.rs b/tests/ui/const-generics/associated_const_equality/equality_bound_with_infer.rs new file mode 100644 index 0000000000000..f45b7c3268b17 --- /dev/null +++ b/tests/ui/const-generics/associated_const_equality/equality_bound_with_infer.rs @@ -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: u32; +} + +impl Foo for () { + const ASSOC: u32 = N; +} + +fn bar = 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 +} diff --git a/tests/ui/const-generics/associated_const_equality/equality_bound_with_infer.stderr b/tests/ui/const-generics/associated_const_equality/equality_bound_with_infer.stderr new file mode 100644 index 0000000000000..00741c901e4c1 --- /dev/null +++ b/tests/ui/const-generics/associated_const_equality/equality_bound_with_infer.stderr @@ -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 = 10>>() {} + | ^^^^^^^^^^^^^ required by this bound in `bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.rs b/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.rs new file mode 100644 index 0000000000000..99318ef75984e --- /dev/null +++ b/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.rs @@ -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 AssocConst for (T,) { + const A: u8 = 0; +} + +trait Trait {} + +impl Trait for () where (U,): AssocConst {} +//~^ 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() {} diff --git a/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.stderr b/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.stderr new file mode 100644 index 0000000000000..e6799ec5c3aa4 --- /dev/null +++ b/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.stderr @@ -0,0 +1,39 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/unconstrained_impl_param.rs:15:45 + | +LL | impl Trait for () where (U,): AssocConst {} + | ^^^^^^^^^ + | + = note: see issue #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 Trait for () where (U,): AssocConst {} + | ^ 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 Trait for () where (U,): AssocConst {} + | ^^^^^ ^^ --------- 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`. diff --git a/tests/crashes/auxiliary/aux133199.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/cross-crate-2.rs similarity index 67% rename from tests/crashes/auxiliary/aux133199.rs rename to tests/ui/const-generics/generic_const_exprs/auxiliary/cross-crate-2.rs index 40765d92fbfe9..a8bda14f4bd81 100644 --- a/tests/crashes/auxiliary/aux133199.rs +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/cross-crate-2.rs @@ -1,9 +1,9 @@ #![allow(incomplete_features)] #![feature(generic_const_exprs)] -pub struct FixedBitSet; +pub struct Foo; -impl FixedBitSet +impl Foo where [u8; N.div_ceil(8)]: Sized, { diff --git a/tests/ui/const-generics/generic_const_exprs/cross-crate-2.rs b/tests/ui/const-generics/generic_const_exprs/cross-crate-2.rs new file mode 100644 index 0000000000000..77998c7ec0a14 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross-crate-2.rs @@ -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(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr index f454ff4e6c036..6b095f3818a16 100644 --- a/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr @@ -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::() } 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::() } else { 3 }]; // lint on stable, error with gce | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr index f6119c17bf47e..12ac980c97544 100644 --- a/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr @@ -9,8 +9,19 @@ help: try adding a `where` bound LL | fn foo() 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() 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::() } 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::() } 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() 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::() } 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 diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs b/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs index 107466cd1d9ca..6b3c8f84be3d1 100644 --- a/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs @@ -9,7 +9,8 @@ use std::mem::size_of; fn foo() { [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 diff --git a/tests/ui/const-generics/generic_const_exprs/different-fn.stderr b/tests/ui/const-generics/generic_const_exprs/different-fn.stderr index ac80463480db1..52917df0da157 100644 --- a/tests/ui/const-generics/generic_const_exprs/different-fn.stderr +++ b/tests/ui/const-generics/generic_const_exprs/different-fn.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/different-fn.rs:10:5 | LL | [0; size_of::>()] - | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::()`, found `0` + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::()`, found `size_of::>()` | = note: expected constant `size_of::()` - found constant `0` + found constant `size_of::>()` error: unconstrained generic constant --> $DIR/different-fn.rs:10:9 diff --git a/tests/ui/const-generics/generic_const_exprs/serializing_error_guaranteed.rs b/tests/ui/const-generics/generic_const_exprs/serializing_error_guaranteed.rs new file mode 100644 index 0000000000000..83b73350f83b6 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/serializing_error_guaranteed.rs @@ -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([(); f::()]) +where + [(); f::()]:; + +const fn f() -> usize { + panic!() +} diff --git a/tests/ui/const-generics/issues/issue-71202.rs b/tests/ui/const-generics/issues/issue-71202.rs index 0f955414d843e..8ff49b55e6fd9 100644 --- a/tests/ui/const-generics/issues/issue-71202.rs +++ b/tests/ui/const-generics/issues/issue-71202.rs @@ -25,7 +25,9 @@ impl DataHolder { } >::VALUE - } as usize] = []; //~ ERROR unconstrained generic constant + } as usize] = []; + //~^ ERROR unconstrained generic constant + //~^^ ERROR mismatched types } fn main() {} diff --git a/tests/ui/const-generics/issues/issue-71202.stderr b/tests/ui/const-generics/issues/issue-71202.stderr index cc3603d1145c3..b7c3db494a576 100644 --- a/tests/ui/const-generics/issues/issue-71202.stderr +++ b/tests/ui/const-generics/issues/issue-71202.stderr @@ -59,5 +59,49 @@ LL + >::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; + } + + >::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; + } + + >::VALUE + } as usize` + found constant `0` + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-83765.rs b/tests/ui/const-generics/issues/issue-83765.rs index 0959f771c22ed..f31c61408e9c6 100644 --- a/tests/ui/const-generics/issues/issue-83765.rs +++ b/tests/ui/const-generics/issues/issue-83765.rs @@ -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 { + //~^ 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 { //~^ 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 TensorDimension for Vec { } impl TensorSize for Vec { fn size(&self) -> [usize; 1] { + //~^ ERROR: method not compatible with trait [self.len()] } } impl Broadcastable for Vec { type Element = T; fn bget(&self, index: [usize; 1]) -> Option { + //~^ ERROR: method not compatible with trait self.get(index[0]).cloned() } } diff --git a/tests/ui/const-generics/issues/issue-83765.stderr b/tests/ui/const-generics/issues/issue-83765.stderr index 6b62012c14fc7..5a06ee7ddbc03 100644 --- a/tests/ui/const-generics/issues/issue-83765.stderr +++ b/tests/ui/const-generics/issues/issue-83765.stderr @@ -1,43 +1,23 @@ -error[E0391]: cycle detected when resolving instance `::DIM, DIM> as TensorDimension>::DIM` - --> $DIR/issue-83765.rs:5:5 - | -LL | const DIM: usize; - | ^^^^^^^^^^^^^^^^ - | -note: ...which requires computing candidate for `::DIM, DIM> as TensorDimension>`... - --> $DIR/issue-83765.rs:4:1 - | -LL | trait TensorDimension { - | ^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires resolving instance `::DIM, DIM> as TensorDimension>::DIM`, completing the cycle -note: cycle used when checking assoc item `::size` is compatible with trait definition - --> $DIR/issue-83765.rs:51:5 +error[E0308]: method not compatible with trait + --> $DIR/issue-83765.rs:47: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 `::DIM, DIM> as TensorDimension>::DIM` - --> $DIR/issue-83765.rs:5:5 - | -LL | const DIM: usize; - | ^^^^^^^^^^^^^^^^ - | -note: ...which requires computing candidate for `::DIM, DIM> as TensorDimension>`... - --> $DIR/issue-83765.rs:4:1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` | -LL | trait TensorDimension { - | ^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires resolving instance `::DIM, DIM> as TensorDimension>::DIM`, completing the cycle -note: cycle used when checking assoc item `::bget` is compatible with trait definition - --> $DIR/issue-83765.rs:58:5 + = note: expected constant `Self::DIM` + found constant `DIM` + +error[E0308]: method not compatible with trait + --> $DIR/issue-83765.rs:55:5 | LL | fn bget(&self, index: [usize; DIM]) -> Option { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = 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 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` error[E0308]: method not compatible with trait - --> $DIR/issue-83765.rs:82:5 + --> $DIR/issue-83765.rs:84:5 | LL | fn size(&self) -> [usize; DIM] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` @@ -46,7 +26,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:96:5 | LL | fn bget(&self, index: [usize; DIM]) -> Option { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` @@ -54,7 +34,127 @@ LL | fn bget(&self, index: [usize; DIM]) -> Option { = 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: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 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 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 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; + | ^^^^^^^^^ required by this bound in `Broadcastable::bget` +help: try adding a `where` bound + | +LL | fn bget(&self, index: [usize; DIM]) -> Option 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: E0308, E0391. -For more information about an error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr index 9fcb26c20a682..81be8c8362e35 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr +++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr @@ -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(, polarity:Positive), bound_vars: [] }]`... note: ...which requires computing type of `Bar::{opaque#0}`... --> $DIR/in-where-clause.rs:5:12