diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f2061f3088a25..eda9bea396d62 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -141,16 +141,11 @@ impl Path { /// Check if this path is potentially a trivial const arg, i.e., one that can _potentially_ /// be represented without an anon const in the HIR. /// - /// If `allow_mgca_arg` is true (as should be the case in most situations when - /// `#![feature(min_generic_const_args)]` is enabled), then this always returns true - /// because all paths are valid. - /// - /// Otherwise, it returns true iff the path has exactly one segment, and it has no generic args + /// Returns true iff the path has exactly one segment, and it has no generic args /// (i.e., it is _potentially_ a const parameter). #[tracing::instrument(level = "debug", ret)] - pub fn is_potential_trivial_const_arg(&self, allow_mgca_arg: bool) -> bool { - allow_mgca_arg - || self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none()) + pub fn is_potential_trivial_const_arg(&self) -> bool { + self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none()) } } @@ -1372,6 +1367,15 @@ pub enum UnsafeSource { UserProvided, } +/// Track whether under `feature(min_generic_const_args)` this anon const +/// was explicitly disambiguated as an anon const or not through the use of +/// `const { ... }` syntax. +#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, Walkable)] +pub enum MgcaDisambiguation { + AnonConst, + Direct, +} + /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. /// These are usually found nested inside types (e.g., array lengths) @@ -1381,6 +1385,7 @@ pub enum UnsafeSource { pub struct AnonConst { pub id: NodeId, pub value: Box, + pub mgca_disambiguation: MgcaDisambiguation, } /// An expression. @@ -1399,26 +1404,20 @@ impl Expr { /// /// This will unwrap at most one block level (curly braces). After that, if the expression /// is a path, it mostly dispatches to [`Path::is_potential_trivial_const_arg`]. - /// See there for more info about `allow_mgca_arg`. /// - /// The only additional thing to note is that when `allow_mgca_arg` is false, this function - /// will only allow paths with no qself, before dispatching to the `Path` function of - /// the same name. + /// This function will only allow paths with no qself, before dispatching to the `Path` + /// function of the same name. /// /// Does not ensure that the path resolves to a const param/item, the caller should check this. /// This also does not consider macros, so it's only correct after macro-expansion. - pub fn is_potential_trivial_const_arg(&self, allow_mgca_arg: bool) -> bool { + pub fn is_potential_trivial_const_arg(&self) -> bool { let this = self.maybe_unwrap_block(); - if allow_mgca_arg { - matches!(this.kind, ExprKind::Path(..)) + if let ExprKind::Path(None, path) = &this.kind + && path.is_potential_trivial_const_arg() + { + true } else { - if let ExprKind::Path(None, path) = &this.kind - && path.is_potential_trivial_const_arg(allow_mgca_arg) - { - true - } else { - false - } + false } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index dde773fd147da..20ab3eb74c035 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -415,6 +415,7 @@ macro_rules! common_visitor_and_walkers { UnsafeBinderCastKind, BinOpKind, BlockCheckMode, + MgcaDisambiguation, BorrowKind, BoundAsyncness, BoundConstness, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 524f8b054cb49..891717a6b4970 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -484,7 +484,11 @@ impl<'hir> LoweringContext<'_, 'hir> { arg }; - let anon_const = AnonConst { id: node_id, value: const_value }; + let anon_const = AnonConst { + id: node_id, + value: const_value, + mgca_disambiguation: MgcaDisambiguation::AnonConst, + }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); } else { real_args.push(arg); diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 8d7351d3a510c..f6edcaa64dfef 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -281,6 +281,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_const_arg_expr_field(&mut self, field: &'hir ConstArgExprField<'hir>) { + self.insert(field.span, field.hir_id, Node::ConstArgExprField(field)); + self.with_parent(field.hir_id, |this| { + intravisit::walk_const_arg_expr_field(this, field); + }) + } + fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) { self.insert(stmt.span, stmt.hir_id, Node::Stmt(stmt)); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1f36454ec861a..56c68910ef255 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1206,7 +1206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .and_then(|partial_res| partial_res.full_res()) { if !res.matches_ns(Namespace::TypeNS) - && path.is_potential_trivial_const_arg(false) + && path.is_potential_trivial_const_arg() { debug!( "lower_generic_arg: Lowering type argument as const argument: {:?}", @@ -2276,11 +2276,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> &'hir hir::ConstArg<'hir> { let tcx = self.tcx; - let ct_kind = if path - .is_potential_trivial_const_arg(tcx.features().min_generic_const_args()) - && (tcx.features().min_generic_const_args() - || matches!(res, Res::Def(DefKind::ConstParam, _))) - { + let is_trivial_path = path.is_potential_trivial_const_arg() + && matches!(res, Res::Def(DefKind::ConstParam, _)); + let ct_kind = if is_trivial_path || tcx.features().min_generic_const_args() { let qpath = self.lower_qpath( ty_id, &None, @@ -2359,6 +2357,81 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + #[instrument(level = "debug", skip(self), ret)] + fn lower_expr_to_const_arg_direct(&mut self, expr: &Expr) -> hir::ConstArg<'hir> { + let overly_complex_const = |this: &mut Self| { + let e = this.dcx().struct_span_err( + expr.span, + "complex const arguments must be placed inside of a `const` block", + ); + + ConstArg { hir_id: this.next_id(), kind: hir::ConstArgKind::Error(expr.span, e.emit()) } + }; + + match &expr.kind { + ExprKind::Path(qself, path) => { + let qpath = self.lower_qpath( + expr.id, + qself, + path, + ParamMode::Explicit, + AllowReturnTypeNotation::No, + // FIXME(mgca): update for `fn foo() -> Bar>` support + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ); + + ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Path(qpath) } + } + ExprKind::Struct(se) => { + let path = self.lower_qpath( + expr.id, + &se.qself, + &se.path, + ParamMode::Explicit, + AllowReturnTypeNotation::No, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ); + + let fields = self.arena.alloc_from_iter(se.fields.iter().map(|f| { + let hir_id = self.lower_node_id(f.id); + self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField); + + let expr = if let ExprKind::ConstBlock(anon_const) = &f.expr.kind { + self.lower_anon_const_to_const_arg_direct(anon_const) + } else { + self.lower_expr_to_const_arg_direct(&f.expr) + }; + + &*self.arena.alloc(hir::ConstArgExprField { + hir_id, + field: self.lower_ident(f.ident), + expr: self.arena.alloc(expr), + span: self.lower_span(f.span), + }) + })); + + ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Struct(path, fields) } + } + ExprKind::Underscore => ConstArg { + hir_id: self.lower_node_id(expr.id), + kind: hir::ConstArgKind::Infer(expr.span, ()), + }, + ExprKind::Block(block, _) => { + if let [stmt] = block.stmts.as_slice() + && let StmtKind::Expr(expr) = &stmt.kind + && matches!(expr.kind, ExprKind::Path(..) | ExprKind::Struct(..)) + { + return self.lower_expr_to_const_arg_direct(expr); + } + + overly_complex_const(self) + } + _ => overly_complex_const(self), + } + } + /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_anon_const`]. fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> { @@ -2379,12 +2452,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { &anon.value }; + + if tcx.features().min_generic_const_args() { + match anon.mgca_disambiguation { + MgcaDisambiguation::AnonConst => { + let lowered_anon = self.lower_anon_const_to_anon_const(anon); + return ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Anon(lowered_anon), + }; + } + MgcaDisambiguation::Direct => return self.lower_expr_to_const_arg_direct(expr), + } + } + let maybe_res = self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); if let ExprKind::Path(qself, path) = &expr.kind - && path.is_potential_trivial_const_arg(tcx.features().min_generic_const_args()) - && (tcx.features().min_generic_const_args() - || matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _)))) + && path.is_potential_trivial_const_arg() + && matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))) { let qpath = self.lower_qpath( expr.id, @@ -2392,7 +2478,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path, ParamMode::Explicit, AllowReturnTypeNotation::No, - // FIXME(mgca): update for `fn foo() -> Bar>` support ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 2d87d8c84d7c9..2d1e6d346f624 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -514,6 +514,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); gate_all!(postfix_match, "postfix match is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); + gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental"); gate_all!(global_registration, "global registration is experimental"); gate_all!(return_type_notation, "return type notation is experimental"); gate_all!(pin_ergonomics, "pinned reference syntax is experimental"); diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index ddc59bfe1414a..9de70b8ced1da 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -17,7 +17,7 @@ mod llvm_enzyme { use rustc_ast::{ self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemKind, BindingMode, FnRetTy, FnSig, GenericArg, GenericArgs, GenericParamKind, Generics, ItemKind, - MetaItemInner, PatKind, Path, PathSegment, TyKind, Visibility, + MetaItemInner, MgcaDisambiguation, PatKind, Path, PathSegment, TyKind, Visibility, }; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::{Ident, Span, Symbol, sym}; @@ -558,7 +558,11 @@ mod llvm_enzyme { } GenericParamKind::Const { .. } => { let expr = ecx.expr_path(ast::Path::from_ident(p.ident)); - let anon_const = AnonConst { id: ast::DUMMY_NODE_ID, value: expr }; + let anon_const = AnonConst { + id: ast::DUMMY_NODE_ID, + value: expr, + mgca_disambiguation: MgcaDisambiguation::Direct, + }; Some(AngleBracketedArg::Arg(GenericArg::Const(anon_const))) } GenericParamKind::Lifetime { .. } => None, @@ -813,6 +817,7 @@ mod llvm_enzyme { let anon_const = rustc_ast::AnonConst { id: ast::DUMMY_NODE_ID, value: ecx.expr_usize(span, 1 + x.width as usize), + mgca_disambiguation: MgcaDisambiguation::Direct, }; TyKind::Array(ty.clone(), anon_const) }; @@ -827,6 +832,7 @@ mod llvm_enzyme { let anon_const = rustc_ast::AnonConst { id: ast::DUMMY_NODE_ID, value: ecx.expr_usize(span, x.width as usize), + mgca_disambiguation: MgcaDisambiguation::Direct, }; let kind = TyKind::Array(ty.clone(), anon_const); let ty = diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs index 87a5a440140e0..4126547b0515a 100644 --- a/compiler/rustc_builtin_macros/src/pattern_type.rs +++ b/compiler/rustc_builtin_macros/src/pattern_type.rs @@ -1,5 +1,5 @@ use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast, token}; +use rustc_ast::{AnonConst, DUMMY_NODE_ID, MgcaDisambiguation, Ty, TyPat, TyPatKind, ast, token}; use rustc_errors::PResult; use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_parse::exp; @@ -60,8 +60,20 @@ fn ty_pat(kind: TyPatKind, span: Span) -> TyPat { fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> TyPat { let kind = match pat.kind { ast::PatKind::Range(start, end, include_end) => TyPatKind::Range( - start.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })), - end.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })), + start.map(|value| { + Box::new(AnonConst { + id: DUMMY_NODE_ID, + value, + mgca_disambiguation: MgcaDisambiguation::Direct, + }) + }), + end.map(|value| { + Box::new(AnonConst { + id: DUMMY_NODE_ID, + value, + mgca_disambiguation: MgcaDisambiguation::Direct, + }) + }), include_end, ), ast::PatKind::Or(variants) => { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 0bce31beb8b87..d071188bcc799 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -2,7 +2,7 @@ use cranelift_codegen::ir::immediates::Offset32; use rustc_abi::Endian; -use rustc_middle::ty::SimdAlign; +use rustc_middle::ty::{SimdAlign, ValTreeKindExt}; use super::*; use crate::prelude::*; @@ -143,7 +143,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let total_len = lane_count * 2; - let indexes = idx.iter().map(|idx| idx.unwrap_leaf().to_u32()).collect::>(); + let indexes = idx + .iter() + .map(|idx| idx.to_value().valtree.unwrap_leaf().to_u32()) + .collect::>(); for &idx in &indexes { assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len); @@ -962,6 +965,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let ptr_val = ptr.load_scalar(fx); let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0] + .to_value() + .valtree .unwrap_leaf() .to_simd_alignment(); @@ -1007,6 +1012,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let ret_lane_layout = fx.layout_of(ret_lane_ty); let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0] + .to_value() + .valtree .unwrap_leaf() .to_simd_alignment(); @@ -1060,6 +1067,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let ptr_val = ptr.load_scalar(fx); let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0] + .to_value() + .valtree .unwrap_leaf() .to_simd_alignment(); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 84fc6ebbc3172..81758403ff480 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -13,7 +13,9 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::{self as hir}; use rustc_middle::mir::BinOp; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; -use rustc_middle::ty::{self, GenericArgsRef, Instance, SimdAlign, Ty, TyCtxt, TypingEnv}; +use rustc_middle::ty::{ + self, GenericArgsRef, Instance, SimdAlign, Ty, TyCtxt, TypingEnv, ValTreeKindExt, +}; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate}; @@ -1459,7 +1461,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( .iter() .enumerate() .map(|(arg_idx, val)| { - let idx = val.unwrap_leaf().to_i32(); + let idx = val.to_value().valtree.unwrap_leaf().to_i32(); if idx >= i32::try_from(total_len).unwrap() { bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds { span, @@ -1857,6 +1859,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // The memory addresses corresponding to the “off” lanes are not accessed. let alignment = fn_args[3].expect_const().to_value().valtree.unwrap_branch()[0] + .to_value() + .valtree .unwrap_leaf() .to_simd_alignment(); @@ -1952,6 +1956,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // The memory addresses corresponding to the “off” lanes are not accessed. let alignment = fn_args[3].expect_const().to_value().valtree.unwrap_branch()[0] + .to_value() + .valtree .unwrap_leaf() .to_simd_alignment(); diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 11b6ab3cdf1ab..44ff252ad51c8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -1,7 +1,7 @@ use rustc_abi::BackendRepr; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, ValTreeKindExt}; use rustc_middle::{bug, mir, span_bug}; use super::FunctionCx; @@ -79,12 +79,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // A SIMD type has a single field, which is an array. let fields = val.unwrap_branch(); assert_eq!(fields.len(), 1); - let array = fields[0].unwrap_branch(); + let array = fields[0].to_value().valtree.unwrap_branch(); // Iterate over the array elements to obtain the values in the vector. let values: Vec<_> = array .iter() .map(|field| { - if let Some(prim) = field.try_to_scalar() { + if let Some(prim) = field.to_value().valtree.try_to_scalar() { let layout = bx.layout_of(field_ty); let BackendRepr::Scalar(scalar) = layout.backend_repr else { bug!("from_const: invalid ByVal layout: {:#?}", layout); diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index aeb7401182347..2e4775e42cba6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,6 +1,6 @@ use rustc_abi::WrappingRange; use rustc_middle::mir::SourceInfo; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, ValTreeKindExt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::sym; @@ -102,7 +102,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let parse_atomic_ordering = |ord: ty::Value<'tcx>| { - let discr = ord.valtree.unwrap_branch()[0].unwrap_leaf(); + let discr = ord.valtree.unwrap_branch()[0].to_value().valtree.unwrap_leaf(); discr.to_atomic_ordering() }; diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 7c41258ebfe5f..a3cb6570ff83d 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -3,7 +3,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::layout::{LayoutCx, TyAndLayout}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, ValTreeKindExt}; use rustc_middle::{bug, mir}; use rustc_span::DUMMY_SP; use tracing::{debug, instrument, trace}; @@ -36,13 +36,17 @@ fn branches<'tcx>( // For enums, we prepend their variant index before the variant's fields so we can figure out // the variant again when just seeing a valtree. if let Some(variant) = variant { - branches.push(ty::ValTree::from_scalar_int(*ecx.tcx, variant.as_u32().into())); + branches.push(ty::Const::new_value( + *ecx.tcx, + ty::ValTree::from_scalar_int(*ecx.tcx, variant.as_u32().into()), + ecx.tcx.types.u32, + )); } for i in 0..field_count { let field = ecx.project_field(&place, FieldIdx::from_usize(i)).unwrap(); let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?; - branches.push(valtree); + branches.push(ty::Const::new_value(*ecx.tcx, valtree, field.layout.ty)); } // Have to account for ZSTs here @@ -65,7 +69,7 @@ fn slice_branches<'tcx>( for i in 0..n { let place_elem = ecx.project_index(place, i).unwrap(); let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?; - elems.push(valtree); + elems.push(ty::Const::new_value(*ecx.tcx, valtree, place_elem.layout.ty)); } Ok(ty::ValTree::from_branches(*ecx.tcx, elems)) @@ -201,7 +205,7 @@ fn reconstruct_place_meta<'tcx>( |ty| ty, || { let branches = last_valtree.unwrap_branch(); - last_valtree = *branches.last().unwrap(); + last_valtree = branches.last().unwrap().to_value().valtree; debug!(?branches, ?last_valtree); }, ); @@ -306,7 +310,8 @@ pub fn valtree_to_const_value<'tcx>( for (i, &inner_valtree) in branches.iter().enumerate() { let field = layout.field(&LayoutCx::new(tcx, typing_env), i); if !field.is_zst() { - let cv = ty::Value { valtree: inner_valtree, ty: field.ty }; + let cv = + ty::Value { valtree: inner_valtree.to_value().valtree, ty: field.ty }; return valtree_to_const_value(tcx, typing_env, cv); } } @@ -397,7 +402,7 @@ fn valtree_into_mplace<'tcx>( let (place_adjusted, branches, variant_idx) = match ty.kind() { ty::Adt(def, _) if def.is_enum() => { // First element of valtree corresponds to variant - let scalar_int = branches[0].unwrap_leaf(); + let scalar_int = branches[0].to_value().valtree.unwrap_leaf(); let variant_idx = VariantIdx::from_u32(scalar_int.to_u32()); let variant = def.variant(variant_idx); debug!(?variant); @@ -425,7 +430,7 @@ fn valtree_into_mplace<'tcx>( }; debug!(?place_inner); - valtree_into_mplace(ecx, &place_inner, *inner_valtree); + valtree_into_mplace(ecx, &place_inner, inner_valtree.to_value().valtree); dump_place(ecx, &place_inner); } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs index bae423840ee1b..1b9c9da8f87a1 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs @@ -3,7 +3,7 @@ use rustc_abi::{BackendRepr, Endian}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_apfloat::{Float, Round}; use rustc_middle::mir::interpret::{InterpErrorKind, Pointer, UndefinedBehaviorInfo}; -use rustc_middle::ty::{FloatTy, ScalarInt, SimdAlign}; +use rustc_middle::ty::{FloatTy, ScalarInt, SimdAlign, ValTreeKindExt}; use rustc_middle::{bug, err_ub_format, mir, span_bug, throw_unsup_format, ty}; use rustc_span::{Symbol, sym}; use tracing::trace; @@ -552,8 +552,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert_eq!(u64::try_from(index_len).unwrap(), dest_len); for i in 0..dest_len { - let src_index: u64 = - index[usize::try_from(i).unwrap()].unwrap_leaf().to_u32().into(); + let src_index: u64 = index[usize::try_from(i).unwrap()] + .to_value() + .valtree + .unwrap_leaf() + .to_u32() + .into(); let dest = self.project_index(&dest, i)?; let val = if src_index < left_len { @@ -658,6 +662,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ptr, dest_layout, generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0] + .to_value() + .valtree .unwrap_leaf() .to_simd_alignment(), )?; @@ -690,6 +696,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ptr, args[2].layout, generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0] + .to_value() + .valtree .unwrap_leaf() .to_simd_alignment(), )?; diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 6be65b0fff16f..e5c06889f3e06 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -2,8 +2,8 @@ use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::literal; use rustc_ast::{ - self as ast, AnonConst, AttrItem, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, - UnOp, attr, token, tokenstream, + self as ast, AnonConst, AttrItem, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, + MgcaDisambiguation, PatKind, UnOp, attr, token, tokenstream, }; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; @@ -101,6 +101,7 @@ impl<'a> ExtCtxt<'a> { attrs: AttrVec::new(), tokens: None, }), + mgca_disambiguation: MgcaDisambiguation::Direct, } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index db88de828aafd..cda5aa2acd8dd 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -494,6 +494,7 @@ impl<'hir, Unambig> ConstArg<'hir, Unambig> { pub fn span(&self) -> Span { match self.kind { + ConstArgKind::Struct(path, _) => path.span(), ConstArgKind::Path(path) => path.span(), ConstArgKind::Anon(anon) => anon.span, ConstArgKind::Error(span, _) => span, @@ -513,6 +514,8 @@ pub enum ConstArgKind<'hir, Unambig = ()> { /// However, in the future, we'll be using it for all of those. Path(QPath<'hir>), Anon(&'hir AnonConst), + /// Represents construction of struct/struct variants + Struct(QPath<'hir>, &'hir [&'hir ConstArgExprField<'hir>]), /// Error const Error(Span, ErrorGuaranteed), /// This variant is not always used to represent inference consts, sometimes @@ -520,6 +523,14 @@ pub enum ConstArgKind<'hir, Unambig = ()> { Infer(Span, Unambig), } +#[derive(Clone, Copy, Debug, HashStable_Generic)] +pub struct ConstArgExprField<'hir> { + pub hir_id: HirId, + pub span: Span, + pub field: Ident, + pub expr: &'hir ConstArg<'hir>, +} + #[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct InferArg { #[stable_hasher(ignore)] @@ -4646,6 +4657,7 @@ pub enum Node<'hir> { ConstArg(&'hir ConstArg<'hir>), Expr(&'hir Expr<'hir>), ExprField(&'hir ExprField<'hir>), + ConstArgExprField(&'hir ConstArgExprField<'hir>), Stmt(&'hir Stmt<'hir>), PathSegment(&'hir PathSegment<'hir>), Ty(&'hir Ty<'hir>), @@ -4705,6 +4717,7 @@ impl<'hir> Node<'hir> { Node::AssocItemConstraint(c) => Some(c.ident), Node::PatField(f) => Some(f.ident), Node::ExprField(f) => Some(f.ident), + Node::ConstArgExprField(f) => Some(f.field), Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident), Node::Param(..) | Node::AnonConst(..) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 0b83e7239a992..d1a1a30198df3 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -396,6 +396,9 @@ pub trait Visitor<'v>: Sized { fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result { walk_expr_field(self, field) } + fn visit_const_arg_expr_field(&mut self, field: &'v ConstArgExprField<'v>) -> Self::Result { + walk_const_arg_expr_field(self, field) + } fn visit_pattern_type_pattern(&mut self, p: &'v TyPat<'v>) -> Self::Result { walk_ty_pat(self, p) } @@ -954,6 +957,17 @@ pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField try_visit!(visitor.visit_ident(*ident)); visitor.visit_expr(*expr) } + +pub fn walk_const_arg_expr_field<'v, V: Visitor<'v>>( + visitor: &mut V, + field: &'v ConstArgExprField<'v>, +) -> V::Result { + let ConstArgExprField { hir_id, field, expr, span: _ } = field; + try_visit!(visitor.visit_id(*hir_id)); + try_visit!(visitor.visit_ident(*field)); + visitor.visit_const_arg_unambig(*expr) +} + /// We track whether an infer var is from a [`Ty`], [`ConstArg`], or [`GenericArg`] so that /// HIR visitors overriding [`Visitor::visit_infer`] can determine what kind of infer is being visited pub enum InferKind<'hir> { @@ -1068,7 +1082,17 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>( ) -> V::Result { let ConstArg { hir_id, kind } = const_arg; try_visit!(visitor.visit_id(*hir_id)); + match kind { + ConstArgKind::Struct(qpath, field_exprs) => { + try_visit!(visitor.visit_qpath(qpath, *hir_id, qpath.span())); + + for field_expr in *field_exprs { + try_visit!(visitor.visit_const_arg_expr_field(field_expr)); + } + + V::Result::output() + } ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, qpath.span()), ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), ConstArgKind::Error(_, _) => V::Result::output(), // errors and spans are not important diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index c881c77f38f15..b3e5d34dbc12d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2263,6 +2263,80 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) .unwrap_or_else(|guar| Const::new_error(tcx, guar)) } + hir::ConstArgKind::Struct(qpath, inits) => { + let (ty, variant_did) = match qpath { + hir::QPath::Resolved(maybe_qself, path) => { + debug!(?maybe_qself, ?path); + let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself)); + let ty = self.lower_resolved_ty_path( + opt_self_ty, + path, + hir_id, + PermitVariants::Yes, + ); + let variant_did = match path.res { + Res::Def(DefKind::Variant | DefKind::Struct, did) => did, + _ => todo!(), + }; + + (ty, variant_did) + } + hir::QPath::TypeRelative(hir_self_ty, segment) => { + debug!(?hir_self_ty, ?segment); + let self_ty = self.lower_ty(hir_self_ty); + let opt_res = self.lower_type_relative_ty_path( + self_ty, + hir_self_ty, + segment, + hir_id, + const_arg.span(), + PermitVariants::Yes, + ); + + let (ty, _, res_def_id) = match opt_res { + Ok(r @ (_, DefKind::Variant | DefKind::Struct, _)) => r, + Ok(_) => todo!(), + Err(e) => return ty::Const::new_error(tcx, e), + }; + + (ty, res_def_id) + } + }; + + let (adt_def, adt_args) = match ty.kind() { + ty::Adt(adt_def, args) => (adt_def, args), + _ => todo!(), + }; + + let variant_def = adt_def.variant_with_id(variant_did); + let variant_idx = adt_def.variant_index_with_id(variant_did).as_u32(); + + let fields = variant_def + .fields + .iter() + .map(|field_def| { + let init_expr = inits + .iter() + .find(|init_expr| init_expr.field.name == field_def.name) + .unwrap(); + self.lower_const_arg( + init_expr.expr, + FeedConstTy::Param(field_def.did, adt_args), + ) + }) + .collect::>(); + + let opt_discr_const = if adt_def.is_enum() { + let valtree = ty::ValTree::from_scalar_int(tcx, variant_idx.into()); + Some(ty::Const::new_value(tcx, valtree, tcx.types.u32)) + } else { + None + }; + + let valtree = + ty::ValTree::from_branches(tcx, opt_discr_const.into_iter().chain(fields)); + ty::Const::new_value(tcx, valtree, ty) + } hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon), hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span), hir::ConstArgKind::Error(_, e) => ty::Const::new_error(tcx, e), @@ -2378,6 +2452,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let expr = &tcx.hir_body(anon.body).value; debug!(?expr); + // If the rhs is an anon const naming generics it shouldn't have + // access to then we lower to `ConstKind::Error`. + if let ty::AnonConstKind::MCG = tcx.anon_const_kind(anon.def_id) + && let Err(e) = tcx.hir_const_arg_anon_check_invalid_param_uses(anon.def_id) + { + return ty::Const::new_error(tcx, e); + } + // FIXME(generic_const_parameter_types): We should use the proper generic args // here. It's only used as a hint for literals so doesn't matter too much to use the right // generic arguments, just weaker type inference. diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b818a697960ac..5e38ab1c4c2bf 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -180,6 +180,8 @@ impl<'a> State<'a> { Node::ConstArg(a) => self.print_const_arg(a), Node::Expr(a) => self.print_expr(a), Node::ExprField(a) => self.print_expr_field(a), + // FIXME(mgca): proper printing for struct exprs + Node::ConstArgExprField(_) => self.word("/* STRUCT EXPR */"), Node::Stmt(a) => self.print_stmt(a), Node::PathSegment(a) => self.print_path_segment(a), Node::Ty(a) => self.print_type(a), @@ -1140,6 +1142,8 @@ impl<'a> State<'a> { fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) { match &const_arg.kind { + // FIXME(mgca): proper printing for struct exprs + ConstArgKind::Struct(..) => self.word("/* STRUCT EXPR */"), ConstArgKind::Path(qpath) => self.print_qpath(qpath, true), ConstArgKind::Anon(anon) => self.print_anon_const(anon), ConstArgKind::Error(_, _) => self.word("/*ERROR*/"), diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 658f9857e5e10..cc85edc081645 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -439,6 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Node::Block(_) | hir::Node::Arm(_) | hir::Node::ExprField(_) + | hir::Node::ConstArgExprField(_) | hir::Node::AnonConst(_) | hir::Node::ConstBlock(_) | hir::Node::ConstArg(_) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index d090eb6338284..18f7984573267 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -117,6 +117,13 @@ fn typeck_with_inspect<'tcx>( return tcx.typeck(typeck_root_def_id); } + if let DefKind::AnonConst = tcx.def_kind(def_id) + && let ty::AnonConstKind::MCG = tcx.anon_const_kind(def_id) + && let Err(e) = tcx.hir_const_arg_anon_check_invalid_param_uses(def_id) + { + e.raise_fatal(); + } + let id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(id); let span = tcx.def_span(def_id); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index dca9ed2ef74fb..21b1f1877e738 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1449,6 +1449,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::Node::ConstArg(hir::ConstArg { kind, .. }) => match kind { // Skip encoding defs for these as they should not have had a `DefId` created hir::ConstArgKind::Error(..) + | hir::ConstArgKind::Struct(..) | hir::ConstArgKind::Path(..) | hir::ConstArgKind::Infer(..) => true, hir::ConstArgKind::Anon(..) => false, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index d1d4c32184ee8..4fa39eb83e9e9 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -92,7 +92,7 @@ macro_rules! arena_types { [] name_set: rustc_data_structures::unord::UnordSet, [] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem, [] ordered_name_set: rustc_data_structures::fx::FxIndexSet, - [] valtree: rustc_middle::ty::ValTreeKind<'tcx>, + [] valtree: rustc_middle::ty::ValTreeKind>, [] stable_order_of_exportable_impls: rustc_data_structures::fx::FxIndexMap, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 430cd329408f5..e923102b247f7 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -2,6 +2,8 @@ //! eliminated, and all its methods are now on `TyCtxt`. But the module name //! stays as `map` because there isn't an obviously better name for it. +use std::ops::ControlFlow; + use rustc_abi::ExternAbi; use rustc_ast::visit::{VisitorResult, walk_list}; use rustc_data_structures::fingerprint::Fingerprint; @@ -738,6 +740,7 @@ impl<'tcx> TyCtxt<'tcx> { Node::ConstArg(_) => node_str("const"), Node::Expr(_) => node_str("expr"), Node::ExprField(_) => node_str("expr field"), + Node::ConstArgExprField(_) => node_str("const arg expr field"), Node::Stmt(_) => node_str("stmt"), Node::PathSegment(_) => node_str("path segment"), Node::Ty(_) => node_str("type"), @@ -1006,6 +1009,7 @@ impl<'tcx> TyCtxt<'tcx> { Node::ConstArg(const_arg) => const_arg.span(), Node::Expr(expr) => expr.span, Node::ExprField(field) => field.span, + Node::ConstArgExprField(field) => field.span, Node::Stmt(stmt) => stmt.span, Node::PathSegment(seg) => { let ident_span = seg.ident.span; @@ -1087,6 +1091,47 @@ impl<'tcx> TyCtxt<'tcx> { None } + + pub fn hir_const_arg_anon_check_invalid_param_uses( + self, + anon: LocalDefId, + ) -> Result<(), ErrorGuaranteed> { + struct GenericParamVisitor<'tcx>(TyCtxt<'tcx>); + impl<'tcx> Visitor<'tcx> for GenericParamVisitor<'tcx> { + type NestedFilter = nested_filter::OnlyBodies; + type Result = ControlFlow; + + fn maybe_tcx(&mut self) -> TyCtxt<'tcx> { + self.0 + } + + fn visit_path( + &mut self, + path: &crate::hir::Path<'tcx>, + _id: HirId, + ) -> ControlFlow { + if let Res::Def( + DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam, + _, + ) = path.res + { + let e = self.0.dcx().struct_span_err( + path.span, + "generic parameters may not be used in const operations", + ); + return ControlFlow::Break(e.emit()); + } + + intravisit::walk_path(self, path) + } + } + + let body = self.hir_maybe_body_owned_by(anon).unwrap(); + match GenericParamVisitor(self).visit_expr(&body.value) { + ControlFlow::Break(e) => Err(e), + ControlFlow::Continue(()) => Ok(()), + } + } } impl<'tcx> intravisit::HirTyCtxt<'tcx> for TyCtxt<'tcx> { diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 6985cc7ddcfa1..b3f852308daf3 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -12,7 +12,7 @@ use super::interpret::ReportedErrorInfo; use crate::mir::interpret::{AllocId, AllocRange, ErrorHandled, GlobalAlloc, Scalar, alloc_range}; use crate::mir::{Promoted, pretty_print_const_value}; use crate::ty::print::{pretty_print_const, with_no_trimmed_paths}; -use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt}; +use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt, ValTreeKindExt}; /////////////////////////////////////////////////////////////////////////// /// Evaluated Constants diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index edbb736128cf9..c320b3d1ba751 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -33,7 +33,7 @@ use crate::ty::adjustment::PointerCoercion; use crate::ty::layout::IntegerExt; use crate::ty::{ self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, Ty, - TyCtxt, UpvarArgs, + TyCtxt, UpvarArgs, ValTreeKindExt, }; pub mod visit; diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index a14e47d70821d..d0b14b75fb94e 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -3,48 +3,19 @@ use std::ops::Deref; use rustc_data_structures::intern::Interned; use rustc_hir::def::Namespace; -use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{ + HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, extension, +}; use super::ScalarInt; use crate::mir::interpret::{ErrorHandled, Scalar}; use crate::ty::print::{FmtPrinter, PrettyPrinter}; use crate::ty::{self, Ty, TyCtxt}; -/// This datastructure is used to represent the value of constants used in the type system. -/// -/// We explicitly choose a different datastructure from the way values are processed within -/// CTFE, as in the type system equal values (according to their `PartialEq`) must also have -/// equal representation (`==` on the rustc data structure, e.g. `ValTree`) and vice versa. -/// Since CTFE uses `AllocId` to represent pointers, it often happens that two different -/// `AllocId`s point to equal values. So we may end up with different representations for -/// two constants whose value is `&42`. Furthermore any kind of struct that has padding will -/// have arbitrary values within that padding, even if the values of the struct are the same. -/// -/// `ValTree` does not have this problem with representation, as it only contains integers or -/// lists of (nested) `ValTree`. -#[derive(Clone, Debug, Hash, Eq, PartialEq)] -#[derive(HashStable, TyEncodable, TyDecodable)] -pub enum ValTreeKind<'tcx> { - /// integers, `bool`, `char` are represented as scalars. - /// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values - /// of these types have the same representation. - Leaf(ScalarInt), - - //SliceOrStr(ValSlice<'tcx>), - // don't use SliceOrStr for now - /// The fields of any kind of aggregate. Structs, tuples and arrays are represented by - /// listing their fields' values in order. - /// - /// Enums are represented by storing their variant index as a u32 field, followed by all - /// the fields of the variant. - /// - /// ZST types are represented as an empty slice. - Branch(Box<[ValTree<'tcx>]>), -} - -impl<'tcx> ValTreeKind<'tcx> { +#[extension(pub trait ValTreeKindExt<'tcx>)] +impl<'tcx> ty::ValTreeKind> { #[inline] - pub fn unwrap_leaf(&self) -> ScalarInt { + fn unwrap_leaf(&self) -> ScalarInt { match self { Self::Leaf(s) => *s, _ => bug!("expected leaf, got {:?}", self), @@ -52,25 +23,25 @@ impl<'tcx> ValTreeKind<'tcx> { } #[inline] - pub fn unwrap_branch(&self) -> &[ValTree<'tcx>] { + fn unwrap_branch(&self) -> &[ty::Const<'tcx>] { match self { Self::Branch(branch) => &**branch, _ => bug!("expected branch, got {:?}", self), } } - pub fn try_to_scalar(&self) -> Option { + fn try_to_scalar(&self) -> Option { self.try_to_scalar_int().map(Scalar::Int) } - pub fn try_to_scalar_int(&self) -> Option { + fn try_to_scalar_int(&self) -> Option { match self { Self::Leaf(s) => Some(*s), Self::Branch(_) => None, } } - pub fn try_to_branch(&self) -> Option<&[ValTree<'tcx>]> { + fn try_to_branch(&self) -> Option<&[ty::Const<'tcx>]> { match self { Self::Branch(branch) => Some(&**branch), Self::Leaf(_) => None, @@ -85,7 +56,13 @@ impl<'tcx> ValTreeKind<'tcx> { /// [dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html#valtrees #[derive(Copy, Clone, Hash, Eq, PartialEq)] #[derive(HashStable)] -pub struct ValTree<'tcx>(pub(crate) Interned<'tcx, ValTreeKind<'tcx>>); +pub struct ValTree<'tcx>(pub(crate) Interned<'tcx, ty::ValTreeKind>>); + +impl<'tcx> rustc_type_ir::inherent::ValTree> for ValTree<'tcx> { + fn kind(&self) -> &ty::ValTreeKind> { + &self + } +} impl<'tcx> ValTree<'tcx> { /// Returns the zero-sized valtree: `Branch([])`. @@ -94,28 +71,33 @@ impl<'tcx> ValTree<'tcx> { } pub fn is_zst(self) -> bool { - matches!(*self, ValTreeKind::Branch(box [])) + matches!(*self, ty::ValTreeKind::Branch(box [])) } pub fn from_raw_bytes(tcx: TyCtxt<'tcx>, bytes: &[u8]) -> Self { - let branches = bytes.iter().map(|&b| Self::from_scalar_int(tcx, b.into())); + let branches = bytes.iter().map(|&b| { + ty::Const::new_value(tcx, Self::from_scalar_int(tcx, b.into()), tcx.types.u8) + }); Self::from_branches(tcx, branches) } - pub fn from_branches(tcx: TyCtxt<'tcx>, branches: impl IntoIterator) -> Self { - tcx.intern_valtree(ValTreeKind::Branch(branches.into_iter().collect())) + pub fn from_branches( + tcx: TyCtxt<'tcx>, + branches: impl IntoIterator>, + ) -> Self { + tcx.intern_valtree(ty::ValTreeKind::Branch(branches.into_iter().collect())) } pub fn from_scalar_int(tcx: TyCtxt<'tcx>, i: ScalarInt) -> Self { - tcx.intern_valtree(ValTreeKind::Leaf(i)) + tcx.intern_valtree(ty::ValTreeKind::Leaf(i)) } } impl<'tcx> Deref for ValTree<'tcx> { - type Target = &'tcx ValTreeKind<'tcx>; + type Target = &'tcx ty::ValTreeKind>; #[inline] - fn deref(&self) -> &&'tcx ValTreeKind<'tcx> { + fn deref(&self) -> &&'tcx ty::ValTreeKind> { &self.0.0 } } @@ -192,9 +174,14 @@ impl<'tcx> Value<'tcx> { _ => return None, } - Some(tcx.arena.alloc_from_iter( - self.valtree.unwrap_branch().into_iter().map(|v| v.unwrap_leaf().to_u8()), - )) + Some( + tcx.arena.alloc_from_iter( + self.valtree + .unwrap_branch() + .into_iter() + .map(|ct| ct.to_value().valtree.unwrap_leaf().to_u8()), + ), + ) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 876297d3e407b..17b4083f3b0bc 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -165,6 +165,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ValueConst = ty::Value<'tcx>; type ExprConst = ty::Expr<'tcx>; type ValTree = ty::ValTree<'tcx>; + type ScalarInt = ty::ScalarInt; type Region = Region<'tcx>; type EarlyParamRegion = ty::EarlyParamRegion; @@ -954,7 +955,7 @@ pub struct CtxtInterners<'tcx> { fields: InternedSet<'tcx, List>, local_def_ids: InternedSet<'tcx, List>, captures: InternedSet<'tcx, List<&'tcx ty::CapturedPlace<'tcx>>>, - valtree: InternedSet<'tcx, ty::ValTreeKind<'tcx>>, + valtree: InternedSet<'tcx, ty::ValTreeKind>>, patterns: InternedSet<'tcx, List>>, outlives: InternedSet<'tcx, List>>, } @@ -2789,7 +2790,7 @@ macro_rules! direct_interners { // crate only, and have a corresponding `mk_` function. direct_interners! { region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>, - valtree: pub(crate) intern_valtree(ValTreeKind<'tcx>): ValTree -> ValTree<'tcx>, + valtree: pub(crate) intern_valtree(ValTreeKind>): ValTree -> ValTree<'tcx>, pat: pub mk_pat(PatternKind<'tcx>): Pattern -> Pattern<'tcx>, const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: pub mk_layout(LayoutData): Layout -> Layout<'tcx>, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d3914d2aee74c..39ddbe6803112 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -74,7 +74,7 @@ pub use self::closure::{ }; pub use self::consts::{ AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, - ExprKind, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKind, Value, + ExprKind, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value, }; pub use self::context::{ CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs index 335e5c0647435..7be73a438833e 100644 --- a/compiler/rustc_middle/src/ty/pattern.rs +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -8,7 +8,7 @@ use rustc_type_ir::{ }; use super::TyCtxt; -use crate::ty; +use crate::ty::{self, ValTreeKindExt}; pub type PatternKind<'tcx> = ir::PatternKind>; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index cff415e9036ad..3d7893717743b 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -267,8 +267,8 @@ TrivialTypeTraversalImpls! { crate::ty::AssocItem, crate::ty::AssocKind, crate::ty::BoundRegion, + crate::ty::ScalarInt, crate::ty::UserTypeAnnotationIndex, - crate::ty::ValTree<'tcx>, crate::ty::abstract_const::NotConstEvaluatable, crate::ty::adjustment::AutoBorrowMutability, crate::ty::adjustment::PointerCoercion, @@ -707,6 +707,29 @@ impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { } } +impl<'tcx> TypeVisitable> for ty::ValTree<'tcx> { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + let inner: &ty::ValTreeKind> = &*self; + inner.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable> for ty::ValTree<'tcx> { + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + let inner: &ty::ValTreeKind> = &*self; + let valtree = folder.cx().intern_valtree(inner.clone().try_fold_with(folder)?); + Ok(valtree) + } + + fn fold_with>>(self, folder: &mut F) -> Self { + let inner: &ty::ValTreeKind> = &*self; + folder.cx().intern_valtree(inner.clone().fold_with(folder)) + } +} + impl<'tcx> TypeVisitable> for rustc_span::ErrorGuaranteed { fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_error(*self) diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs index b221318bf0b10..4708a563e5f98 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -3,6 +3,7 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty; +use rustc_middle::ty::ValTreeKindExt; use rustc_middle::ty::cast::mir_cast_kind; use rustc_span::Span; use rustc_span::source_map::Spanned; diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 433c3e5aaaeec..def7ce339fe3e 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -18,7 +18,9 @@ use rustc_hir::{BindingMode, ByRef, LangItem, LetStmt, LocalSource, Node, Pinned use rustc_middle::middle::region::{self, TempLifetime}; use rustc_middle::mir::*; use rustc_middle::thir::{self, *}; -use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, ValTree, ValTreeKind}; +use rustc_middle::ty::{ + self, CanonicalUserTypeAnnotation, Ty, ValTree, ValTreeKind, ValTreeKindExt, +}; use rustc_middle::{bug, span_bug}; use rustc_pattern_analysis::constructor::RangeEnd; use rustc_pattern_analysis::rustc::{DeconstructedPat, RustcPatCtxt}; @@ -3014,7 +3016,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { bug!("malformed valtree for an enum") }; - let ValTreeKind::Leaf(actual_variant_idx) = ***actual_variant_idx else { + let ValTreeKind::Leaf(actual_variant_idx) = *actual_variant_idx.to_value().valtree + else { bug!("malformed valtree for an enum") }; diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index 1b6d96e49f0c1..4aa204e88cb3a 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::{LangItem, RangeEnd}; use rustc_middle::mir::*; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt, ValTreeKindExt}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; use rustc_span::source_map::Spanned; diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 9665987362202..f765a44156da7 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -897,7 +897,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.tcx, ValTree::from_branches( self.tcx, - [ValTree::from_scalar_int(self.tcx, variant_index.as_u32().into())], + [ty::Const::new_value( + self.tcx, + ValTree::from_scalar_int( + self.tcx, + variant_index.as_u32().into(), + ), + self.tcx.types.u32, + )], ), self.thir[value].ty, ), diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 6e071fb344c44..563212a51f31a 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -63,7 +63,7 @@ pub(crate) fn lit_to_const<'tcx>( // A CStr is a newtype around a byte slice, so we create the inner slice here. // We need a branch for each "level" of the data structure. let bytes = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()); - ty::ValTree::from_branches(tcx, [bytes]) + ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, *inner_ty)]) } (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => { let scalar_int = trunc(n.get(), *ui); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 6316ccf1b8c5b..5688cde06473b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::span_bug; use rustc_middle::thir::{FieldPat, Pat, PatKind}; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, ValTree, + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, ValTree, ValTreeKindExt, }; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span}; @@ -240,13 +240,14 @@ impl<'tcx> ConstToPat<'tcx> { } ty::Adt(adt_def, args) if adt_def.is_enum() => { let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap(); - let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().to_u32()); + let variant_index = + VariantIdx::from_u32(variant_index.to_value().valtree.unwrap_leaf().to_u32()); PatKind::Variant { adt_def: *adt_def, args, variant_index, subpatterns: self.field_pats( - fields.iter().copied().zip( + fields.iter().map(|ct| ct.to_value().valtree).zip( adt_def.variants()[variant_index] .fields .iter() @@ -258,19 +259,23 @@ impl<'tcx> ConstToPat<'tcx> { ty::Adt(def, args) => { assert!(!def.is_union()); // Valtree construction would never succeed for unions. PatKind::Leaf { - subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip( - def.non_enum_variant().fields.iter().map(|field| field.ty(tcx, args)), - )), + subpatterns: self.field_pats( + cv.unwrap_branch().iter().map(|ct| ct.to_value().valtree).zip( + def.non_enum_variant().fields.iter().map(|field| field.ty(tcx, args)), + ), + ), } } ty::Tuple(fields) => PatKind::Leaf { - subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(fields.iter())), + subpatterns: self.field_pats( + cv.unwrap_branch().iter().map(|ct| ct.to_value().valtree).zip(fields.iter()), + ), }, ty::Slice(elem_ty) => PatKind::Slice { prefix: cv .unwrap_branch() .iter() - .map(|val| *self.valtree_to_pat(*val, *elem_ty)) + .map(|val| *self.valtree_to_pat(val.to_value().valtree, *elem_ty)) .collect(), slice: None, suffix: Box::new([]), @@ -279,7 +284,7 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| *self.valtree_to_pat(*val, *elem_ty)) + .map(|val| *self.valtree_to_pat(val.to_value().valtree, *elem_ty)) .collect(), slice: None, suffix: Box::new([]), diff --git a/compiler/rustc_parse/src/parser/asm.rs b/compiler/rustc_parse/src/parser/asm.rs index 41c3b0f0b676a..9d902d0ca4ba2 100644 --- a/compiler/rustc_parse/src/parser/asm.rs +++ b/compiler/rustc_parse/src/parser/asm.rs @@ -1,4 +1,4 @@ -use rustc_ast::{self as ast, AsmMacro}; +use rustc_ast::{self as ast, AsmMacro, MgcaDisambiguation}; use rustc_span::{Span, Symbol, kw}; use super::{ExpKeywordPair, ForceCollect, IdentIsRaw, Trailing, UsePreAttrPos}; @@ -149,7 +149,7 @@ fn parse_asm_operand<'a>( let block = p.parse_block()?; ast::InlineAsmOperand::Label { block } } else if p.eat_keyword(exp!(Const)) { - let anon_const = p.parse_expr_anon_const()?; + let anon_const = p.parse_expr_anon_const(MgcaDisambiguation::AnonConst)?; ast::InlineAsmOperand::Const { anon_const } } else if p.eat_keyword(exp!(Sym)) { let expr = p.parse_expr()?; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index bd495f6ec1acb..a93b1848481bc 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -6,8 +6,8 @@ use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind}; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, - Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, - PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind, + Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, + MgcaDisambiguation, Param, Pat, PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; @@ -2627,7 +2627,11 @@ impl<'a> Parser<'a> { self.dcx().emit_err(UnexpectedConstParamDeclaration { span: param.span(), sugg }); let value = self.mk_expr_err(param.span(), guar); - Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })) + Some(GenericArg::Const(AnonConst { + id: ast::DUMMY_NODE_ID, + value, + mgca_disambiguation: MgcaDisambiguation::Direct, + })) } pub(super) fn recover_const_param_declaration( @@ -2711,7 +2715,11 @@ impl<'a> Parser<'a> { ); let guar = err.emit(); let value = self.mk_expr_err(start.to(expr.span), guar); - return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })); + return Ok(GenericArg::Const(AnonConst { + id: ast::DUMMY_NODE_ID, + value, + mgca_disambiguation: MgcaDisambiguation::Direct, + })); } else if snapshot.token == token::Colon && expr.span.lo() == snapshot.token.span.hi() && matches!(expr.kind, ExprKind::Path(..)) @@ -2780,7 +2788,11 @@ impl<'a> Parser<'a> { ); let guar = err.emit(); let value = self.mk_expr_err(span, guar); - GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }) + GenericArg::Const(AnonConst { + id: ast::DUMMY_NODE_ID, + value, + mgca_disambiguation: MgcaDisambiguation::Direct, + }) } /// Some special error handling for the "top-level" patterns in a match arm, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9e7d4bca37d05..561e40aa6b9f4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -15,8 +15,8 @@ use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::{ self as ast, AnonConst, Arm, AssignOp, AssignOpKind, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, - FnRetTy, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, - UnOp, UnsafeBinderCastKind, YieldKind, + FnRetTy, Label, MacCall, MetaItemLit, MgcaDisambiguation, Movability, Param, RangeLimits, + StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind, }; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; @@ -85,8 +85,11 @@ impl<'a> Parser<'a> { ) } - pub fn parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst> { - self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value }) + pub fn parse_expr_anon_const( + &mut self, + mgca_disambiguation: MgcaDisambiguation, + ) -> PResult<'a, AnonConst> { + self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value, mgca_disambiguation }) } fn parse_expr_catch_underscore( @@ -1615,7 +1618,13 @@ impl<'a> Parser<'a> { let first_expr = self.parse_expr()?; if self.eat(exp!(Semi)) { // Repeating array syntax: `[ 0; 512 ]` - let count = self.parse_expr_anon_const()?; + let count = if self.token.is_keyword(kw::Const) + && self.look_ahead(1, |t| *t == token::OpenBrace) + { + self.parse_expr_anon_const(MgcaDisambiguation::AnonConst)? + } else { + self.parse_expr_anon_const(MgcaDisambiguation::Direct)? + }; self.expect(close)?; ExprKind::Repeat(first_expr, count) } else if self.eat(exp!(Comma)) { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 86991f047e46d..8a926b82e33e9 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1424,7 +1424,7 @@ impl<'a> Parser<'a> { let rhs = if self.eat(exp!(Eq)) { if attr::contains_name(attrs, sym::type_const) { - Some(ConstItemRhs::TypeConst(self.parse_expr_anon_const()?)) + Some(ConstItemRhs::TypeConst(self.parse_const_arg()?)) } else { Some(ConstItemRhs::Body(self.parse_expr()?)) } @@ -1643,8 +1643,11 @@ impl<'a> Parser<'a> { VariantData::Unit(DUMMY_NODE_ID) }; - let disr_expr = - if this.eat(exp!(Eq)) { Some(this.parse_expr_anon_const()?) } else { None }; + let disr_expr = if this.eat(exp!(Eq)) { + Some(this.parse_expr_anon_const(MgcaDisambiguation::AnonConst)?) + } else { + None + }; let vr = ast::Variant { ident, @@ -1857,7 +1860,7 @@ impl<'a> Parser<'a> { if p.token == token::Eq { let mut snapshot = p.create_snapshot_for_diagnostic(); snapshot.bump(); - match snapshot.parse_expr_anon_const() { + match snapshot.parse_expr_anon_const(MgcaDisambiguation::AnonConst) { Ok(const_expr) => { let sp = ty.span.shrink_to_hi().to(const_expr.value.span); p.psess.gated_spans.gate(sym::default_field_values, sp); @@ -2059,7 +2062,7 @@ impl<'a> Parser<'a> { } let default = if self.token == token::Eq { self.bump(); - let const_expr = self.parse_expr_anon_const()?; + let const_expr = self.parse_expr_anon_const(MgcaDisambiguation::AnonConst)?; let sp = ty.span.shrink_to_hi().to(const_expr.value.span); self.psess.gated_spans.gate(sym::default_field_values, sp); Some(const_expr) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 203a93b52012b..a06329636dbf6 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -35,9 +35,9 @@ use rustc_ast::tokenstream::{ }; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID, - DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, - Visibility, VisibilityKind, + self as ast, AnonConst, AttrArgs, AttrId, BlockCheckMode, ByRef, Const, CoroutineKind, + DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, MgcaDisambiguation, + Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; @@ -714,7 +714,10 @@ impl<'a> Parser<'a> { } fn check_const_arg(&mut self) -> bool { - self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const) + let is_mcg_arg = self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const); + let is_mgca_arg = self.is_keyword_ahead(0, &[kw::Const]) + && self.look_ahead(1, |t| *t == token::OpenBrace); + is_mcg_arg || is_mgca_arg } fn check_const_closure(&self) -> bool { @@ -1286,6 +1289,20 @@ impl<'a> Parser<'a> { } } + fn parse_mgca_const_block(&mut self, gate_syntax: bool) -> PResult<'a, AnonConst> { + self.expect_keyword(exp!(Const))?; + let kw_span = self.token.span; + let value = self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?; + if gate_syntax { + self.psess.gated_spans.gate(sym::min_generic_const_args, kw_span.to(value.span)); + } + Ok(AnonConst { + id: ast::DUMMY_NODE_ID, + value, + mgca_disambiguation: MgcaDisambiguation::AnonConst, + }) + } + /// Parses inline const expressions. fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, Box> { self.expect_keyword(exp!(Const))?; @@ -1293,6 +1310,7 @@ impl<'a> Parser<'a> { let anon_const = AnonConst { id: DUMMY_NODE_ID, value: self.mk_expr(blk.span, ExprKind::Block(blk, None)), + mgca_disambiguation: MgcaDisambiguation::AnonConst, }; let blk_span = anon_const.value.span; let kind = if pat { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 437f6da67b74e..463d8b8c8894f 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -4,8 +4,8 @@ use ast::token::IdentIsRaw; use rustc_ast::token::{self, MetaVarKind, Token, TokenKind}; use rustc_ast::{ self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint, - AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, - Path, PathSegment, QSelf, + AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, MgcaDisambiguation, + ParenthesizedArgs, Path, PathSegment, QSelf, }; use rustc_errors::{Applicability, Diag, PResult}; use rustc_span::{BytePos, Ident, Span, kw, sym}; @@ -870,12 +870,17 @@ impl<'a> Parser<'a> { /// the caller. pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> { // Parse const argument. - let value = if self.token.kind == token::OpenBrace { - self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)? + let (value, mgca_disambiguation) = if self.token.kind == token::OpenBrace { + let value = self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?; + (value, MgcaDisambiguation::Direct) + } else if self.token.is_keyword(kw::Const) { + let value = self.parse_mgca_const_block(true)?; + (value.value, MgcaDisambiguation::AnonConst) } else { - self.handle_unambiguous_unbraced_const_arg()? + let value = self.handle_unambiguous_unbraced_const_arg()?; + (value, MgcaDisambiguation::Direct) }; - Ok(AnonConst { id: ast::DUMMY_NODE_ID, value }) + Ok(AnonConst { id: ast::DUMMY_NODE_ID, value, mgca_disambiguation }) } /// Parse a generic argument in a path segment. @@ -976,7 +981,11 @@ impl<'a> Parser<'a> { GenericArg::Type(_) => GenericArg::Type(self.mk_ty(attr_span, TyKind::Err(guar))), GenericArg::Const(_) => { let error_expr = self.mk_expr(attr_span, ExprKind::Err(guar)); - GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value: error_expr }) + GenericArg::Const(AnonConst { + id: ast::DUMMY_NODE_ID, + value: error_expr, + mgca_disambiguation: MgcaDisambiguation::Direct, + }) } GenericArg::Lifetime(lt) => GenericArg::Lifetime(lt), })); diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index df69adce142b8..89bd4fecbc8d8 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -2,9 +2,9 @@ use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy, - GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, - Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, - TyKind, UnsafeBinderTy, + GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MgcaDisambiguation, + MutTy, Mutability, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, + TraitObjectSyntax, Ty, TyKind, UnsafeBinderTy, }; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult}; @@ -658,7 +658,14 @@ impl<'a> Parser<'a> { }; let ty = if self.eat(exp!(Semi)) { - let mut length = self.parse_expr_anon_const()?; + let mut length = if self.token.is_keyword(kw::Const) + && self.look_ahead(1, |t| *t == token::OpenBrace) + { + self.parse_mgca_const_block(false)? + } else { + self.parse_expr_anon_const(MgcaDisambiguation::Direct)? + }; + if let Err(e) = self.expect(exp!(CloseBracket)) { // Try to recover from `X` when `X::` works self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?; @@ -699,8 +706,9 @@ impl<'a> Parser<'a> { _ = self.eat(exp!(Comma)) || self.eat(exp!(Colon)) || self.eat(exp!(Star)); let suggestion_span = self.prev_token.span.with_lo(hi); + // FIXME(mgca): recovery is broken for `const {` args // we first try to parse pattern like `[u8 5]` - let length = match self.parse_expr_anon_const() { + let length = match self.parse_expr_anon_const(MgcaDisambiguation::Direct) { Ok(length) => length, Err(e) => { e.cancel(); @@ -788,7 +796,7 @@ impl<'a> Parser<'a> { // To avoid ambiguity, the type is surrounded by parentheses. fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> { self.expect(exp!(OpenParen))?; - let expr = self.parse_expr_anon_const()?; + let expr = self.parse_expr_anon_const(MgcaDisambiguation::AnonConst)?; self.expect(exp!(CloseParen))?; Ok(TyKind::Typeof(expr)) } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index df86233c2b055..0e356d22a54a1 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -11,7 +11,8 @@ use rustc_middle::middle::stability::EvalResult; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ - self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef, + self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, ValTreeKindExt, + VariantDef, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index ea64a1e6c64dd..2818e2014af4a 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -74,6 +74,12 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { self.invocation_parent.impl_trait_context = orig_itc; } + fn with_direct_const_arg(&mut self, is_direct: bool, f: F) { + let orig = mem::replace(&mut self.invocation_parent.in_direct_const_arg, is_direct); + f(self); + self.invocation_parent.in_direct_const_arg = orig; + } + fn collect_field(&mut self, field: &'a FieldDef, index: Option) { let index = |this: &Self| { index.unwrap_or_else(|| { @@ -357,25 +363,73 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - let parent = self.create_def(constant.id, None, DefKind::AnonConst, constant.value.span); - self.with_parent(parent, |this| visit::walk_anon_const(this, constant)); + if let MgcaDisambiguation::Direct = constant.mgca_disambiguation + && self.resolver.tcx.features().min_generic_const_args() + { + self.with_direct_const_arg(true, |this| { + visit::walk_anon_const(this, constant); + }); + } else { + self.with_direct_const_arg(false, |this| { + let parent = + this.create_def(constant.id, None, DefKind::AnonConst, constant.value.span); + this.with_parent(parent, |this| visit::walk_anon_const(this, constant)); + }) + } } fn visit_expr(&mut self, expr: &'a Expr) { + let handle_const_block = |this: &mut Self, constant: &'a AnonConst, def_kind: DefKind| { + for attr in &expr.attrs { + visit::walk_attribute(this, attr); + } + + let def = this.create_def(constant.id, None, def_kind, constant.value.span); + this.with_direct_const_arg(false, |this| { + this.with_parent(def, |this| visit::walk_anon_const(this, constant)); + }); + }; + let parent_def = match expr.kind { ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id), ExprKind::Closure(..) | ExprKind::Gen(..) => { self.create_def(expr.id, None, DefKind::Closure, expr.span) } ExprKind::ConstBlock(ref constant) => { - for attr in &expr.attrs { - visit::walk_attribute(self, attr); + handle_const_block(self, constant, DefKind::InlineConst); + return; + } + ExprKind::Struct(ref se) if self.invocation_parent.in_direct_const_arg => { + let StructExpr { qself, path, fields, rest } = &**se; + + for init_expr in fields { + if let ExprKind::ConstBlock(ref constant) = init_expr.expr.kind { + handle_const_block(self, constant, DefKind::AnonConst); + } else { + visit::walk_expr_field(self, init_expr); + } + } + + if let Some(qself) = qself { + self.visit_qself(qself); } - let def = - self.create_def(constant.id, None, DefKind::InlineConst, constant.value.span); - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); + self.visit_path(path); + + match rest { + StructRest::Base(expr) => self.visit_expr(expr), + _ => (), + } + return; } + ExprKind::Field(ref init_expr, _) if self.invocation_parent.in_direct_const_arg => { + if let ExprKind::ConstBlock(ref constant) = init_expr.kind { + handle_const_block(self, constant, DefKind::AnonConst); + return; + } else { + self.invocation_parent.parent_def + } + } _ => self.invocation_parent.parent_def, }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a92bc77b5b508..7d31edb724405 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1225,7 +1225,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc if let TyKind::Path(None, ref path) = ty.kind // We cannot disambiguate multi-segment paths right now as that requires type // checking. - && path.is_potential_trivial_const_arg(false) + && path.is_potential_trivial_const_arg() { let mut check_ns = |ns| { self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns) @@ -4839,9 +4839,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { constant, anon_const_kind ); - let is_trivial_const_arg = constant - .value - .is_potential_trivial_const_arg(self.r.tcx.features().min_generic_const_args()); + let is_trivial_const_arg = constant.value.is_potential_trivial_const_arg(); self.resolve_anon_const_manual(is_trivial_const_arg, anon_const_kind, |this| { this.resolve_expr(&constant.value, None) }) @@ -4871,7 +4869,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes, AnonConstKind::InlineConst => ConstantHasGenerics::Yes, AnonConstKind::ConstArg(_) => { - if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg { + if self.r.tcx.features().generic_const_exprs() + || self.r.tcx.features().min_generic_const_args() + || is_trivial_const_arg + { ConstantHasGenerics::Yes } else { ConstantHasGenerics::No(NoConstantGenericsReason::NonTrivialConstArg) @@ -5022,9 +5023,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Constant arguments need to be treated as AnonConst since // that is how they will be later lowered to HIR. if const_args.contains(&idx) { - let is_trivial_const_arg = argument.is_potential_trivial_const_arg( - self.r.tcx.features().min_generic_const_args(), - ); + // FIXME(mgca): legacy const generics doesn't support mgca but maybe + // that's okay. + let is_trivial_const_arg = argument.is_potential_trivial_const_arg(); self.resolve_anon_const_manual( is_trivial_const_arg, AnonConstKind::ConstArg(IsRepeatExpr::No), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7ce70ee9af8d4..09f07d9796c25 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -191,6 +191,7 @@ struct InvocationParent { parent_def: LocalDefId, impl_trait_context: ImplTraitContext, in_attr: bool, + in_direct_const_arg: bool, } impl InvocationParent { @@ -198,6 +199,7 @@ impl InvocationParent { parent_def: CRATE_DEF_ID, impl_trait_context: ImplTraitContext::Existential, in_attr: false, + in_direct_const_arg: false, }; } diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index ee2621af84280..1f0650d95a7ec 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -9,6 +9,7 @@ use rustc_middle::bug; use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer}; use rustc_middle::ty::{ self, GenericArg, GenericArgKind, Instance, ReifyReason, Ty, TyCtxt, TypeVisitableExt, + ValTreeKindExt, }; use tracing::debug; diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 36281ff16bceb..e8625d9ac20b5 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -4,6 +4,7 @@ // tidy-alphabetical-end pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set}; +use rustc_middle::ty::ValTreeKindExt; pub mod layout; mod maybe_transmutable; @@ -158,7 +159,7 @@ mod rustc { .enumerate() .find(|(_, field_def)| name == field_def.name) .unwrap_or_else(|| panic!("There were no fields named `{name}`.")); - fields[field_idx].unwrap_leaf() == ScalarInt::TRUE + fields[field_idx].to_value().valtree.unwrap_leaf() == ScalarInt::TRUE }; Some(Self { diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 4b19d0f16d78a..0be154458858a 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -9,7 +9,7 @@ use rustc_middle::query::Providers; use rustc_middle::thir::visit; use rustc_middle::thir::visit::Visitor; use rustc_middle::ty::abstract_const::CastKind; -use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt, ValTreeKindExt}; use rustc_middle::{bug, mir, thir}; use rustc_span::Span; use tracing::{debug, instrument}; @@ -33,7 +33,7 @@ fn destructure_const<'tcx>( // construct the consts for the elements of the array/slice let field_consts = branches .iter() - .map(|b| ty::Const::new_value(tcx, *b, *inner_ty)) + .map(|b| ty::Const::new_value(tcx, b.to_value().valtree, *inner_ty)) .collect::>(); debug!(?field_consts); @@ -43,7 +43,7 @@ fn destructure_const<'tcx>( ty::Adt(def, args) => { let (variant_idx, branches) = if def.is_enum() { let (head, rest) = branches.split_first().unwrap(); - (VariantIdx::from_u32(head.unwrap_leaf().to_u32()), rest) + (VariantIdx::from_u32(head.to_value().valtree.unwrap_leaf().to_u32()), rest) } else { (FIRST_VARIANT, branches) }; @@ -52,7 +52,8 @@ fn destructure_const<'tcx>( for (field, field_valtree) in iter::zip(fields, branches) { let field_ty = field.ty(tcx, args); - let field_const = ty::Const::new_value(tcx, *field_valtree, field_ty); + let field_const = + ty::Const::new_value(tcx, field_valtree.to_value().valtree, field_ty); field_consts.push(field_const); } debug!(?field_consts); @@ -61,7 +62,9 @@ fn destructure_const<'tcx>( } ty::Tuple(elem_tys) => { let fields = iter::zip(*elem_tys, branches) - .map(|(elem_ty, elem_valtree)| ty::Const::new_value(tcx, *elem_valtree, elem_ty)) + .map(|(elem_ty, elem_valtree)| { + ty::Const::new_value(tcx, elem_valtree.to_value().valtree, elem_ty) + }) .collect::>(); (fields, None) diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 8393bbe5caf83..7146da6203d5b 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -124,3 +124,39 @@ impl HashStable for InferConst { } } } + +/// This datastructure is used to represent the value of constants used in the type system. +/// +/// We explicitly choose a different datastructure from the way values are processed within +/// CTFE, as in the type system equal values (according to their `PartialEq`) must also have +/// equal representation (`==` on the rustc data structure, e.g. `ValTree`) and vice versa. +/// Since CTFE uses `AllocId` to represent pointers, it often happens that two different +/// `AllocId`s point to equal values. So we may end up with different representations for +/// two constants whose value is `&42`. Furthermore any kind of struct that has padding will +/// have arbitrary values within that padding, even if the values of the struct are the same. +/// +/// `ValTree` does not have this problem with representation, as it only contains integers or +/// lists of (nested) `ValTree`. +#[derive_where(Clone, Debug, Hash, Eq, PartialEq; I: Interner)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] +pub enum ValTreeKind { + /// integers, `bool`, `char` are represented as scalars. + /// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values + /// of these types have the same representation. + Leaf(I::ScalarInt), + + //SliceOrStr(ValSlice<'tcx>), + // don't use SliceOrStr for now + /// The fields of any kind of aggregate. Structs, tuples and arrays are represented by + /// listing their fields' values in order. + /// + /// Enums are represented by storing their variant index as a u32 field, followed by all + /// the fields of the variant. + /// + /// ZST types are represented as an empty slice. + Branch(Box<[I::Const]>), +} diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 34b030ee768b6..2c1fc7decc3e7 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -477,7 +477,17 @@ impl FlagComputation { ty::ConstKind::Placeholder(_) => { self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); } - ty::ConstKind::Value(cv) => self.add_ty(cv.ty()), + ty::ConstKind::Value(cv) => { + self.add_ty(cv.ty()); + match cv.valtree().kind() { + ty::ValTreeKind::Leaf(_) => (), + ty::ValTreeKind::Branch(cts) => { + for ct in cts { + self.add_const(*ct); + } + } + } + } ty::ConstKind::Expr(e) => self.add_args(e.args().as_slice()), ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 75ba0231d98cb..b1a722e78f948 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -292,6 +292,11 @@ pub trait ValueConst>: Copy + Debug + Hash + Eq { fn valtree(self) -> I::ValTree; } +pub trait ValTree>: Copy + Debug + Hash + Eq { + // This isnt' `IntoKind` because then we can't return a reference + fn kind(&self) -> &ty::ValTreeKind; +} + pub trait ExprConst>: Copy + Debug + Hash + Eq + Relate { fn args(self) -> I::GenericArgs; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 3884f29a4fc80..03cf738c05987 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -153,7 +153,8 @@ pub trait Interner: type PlaceholderConst: PlaceholderConst; type ValueConst: ValueConst; type ExprConst: ExprConst; - type ValTree: Copy + Debug + Hash + Eq; + type ValTree: ValTree; + type ScalarInt: Copy + Debug + Hash + Eq; // Kinds of regions type Region: Region; diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index fc74cbf478236..db1dbe552bd82 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -600,13 +600,27 @@ pub fn structurally_relate_consts>( } (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2, (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => { - a_val.valtree() == b_val.valtree() + match (a_val.valtree().kind(), b_val.valtree().kind()) { + (ty::ValTreeKind::Leaf(scalar_a), ty::ValTreeKind::Leaf(scalar_b)) => { + scalar_a == scalar_b + } + (ty::ValTreeKind::Branch(branches_a), ty::ValTreeKind::Branch(branches_b)) + if branches_a.len() == branches_b.len() => + { + branches_a + .into_iter() + .zip(branches_b) + .all(|(a, b)| relation.relate(*a, *b).is_ok()) + } + _ => false, + } } // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `generic_const_exprs` can // be stabilized. (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { + // FIXME(mgca): remove this if cfg!(debug_assertions) { let a_ty = cx.type_of(au.def.into()).instantiate(cx, au.args); let b_ty = cx.type_of(bu.def.into()).instantiate(cx, bu.args); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a4f754912aea6..a131b484584b0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -321,6 +321,9 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind hir::ConstArgKind::Path(qpath) => { ConstantKind::Path { path: qpath_to_string(qpath).into() } } + hir::ConstArgKind::Struct(..) => { + ConstantKind::Path { path: "/* STRUCT EXPR */".to_string().into() } + } hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body }, hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => ConstantKind::Infer, } @@ -1813,7 +1816,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T let ct = cx.tcx.normalize_erasing_regions(typing_env, ct); print_const(cx, ct) } - hir::ConstArgKind::Path(..) => { + hir::ConstArgKind::Struct(..) | hir::ConstArgKind::Path(..) => { let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); print_const(cx, ct) } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 060abfd05e042..1220c25c43c3c 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -10,7 +10,9 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_metadata::rendered_const; use rustc_middle::mir; -use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{ + self, GenericArgKind, GenericArgsRef, TyCtxt, TypeVisitableExt, ValTreeKindExt, +}; use rustc_span::symbol::{Symbol, kw, sym}; use tracing::{debug, warn}; use {rustc_ast as ast, rustc_hir as hir}; diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 03cbb0311c6ca..685b0a9c0d60f 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -319,6 +319,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind"); self.body(field!(anon_const.body)); }, + ConstArgKind::Struct(..) => chain!(self, "let ConstArgKind::Struct(..) = {const_arg}.kind"), ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"), ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"), } diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 7e3fa4f9909b3..e43b0b95d9f7f 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -1139,7 +1139,7 @@ pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx ConstItemRhs::Body(body_id) => Some(tcx.hir_body(body_id).value), ConstItemRhs::TypeConst(const_arg) => match const_arg.kind { ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value), - ConstArgKind::Path(_) | ConstArgKind::Error(..) | ConstArgKind::Infer(..) => None, + ConstArgKind::Struct(..) | ConstArgKind::Path(_) | ConstArgKind::Error(..) | ConstArgKind::Infer(..) => None, }, } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index b286701fbed11..afd9601087a77 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -477,11 +477,18 @@ impl HirEqInterExpr<'_, '_, '_> { (ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p), (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body), (ConstArgKind::Infer(..), ConstArgKind::Infer(..)) => true, + (ConstArgKind::Struct(path_a, inits_a), ConstArgKind::Struct(path_b, inits_b)) => { + self.eq_qpath(path_a, path_b) + && inits_a.iter().zip(*inits_b).all(|(init_a, init_b)| { + self.eq_const_arg(init_a.expr, init_b.expr) + }) + } // Use explicit match for now since ConstArg is undergoing flux. - (ConstArgKind::Path(..), ConstArgKind::Anon(..)) - | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) - | (ConstArgKind::Infer(..) | ConstArgKind::Error(..), _) - | (_, ConstArgKind::Infer(..) | ConstArgKind::Error(..)) => false, + (ConstArgKind::Path(..), _) + | (ConstArgKind::Anon(..), _) + | (ConstArgKind::Infer(..), _) + | (ConstArgKind::Struct(..), _) + | (ConstArgKind::Error(..), _) => false, } } @@ -1335,6 +1342,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { match &const_arg.kind { ConstArgKind::Path(path) => self.hash_qpath(path), ConstArgKind::Anon(anon) => self.hash_body(anon.body), + ConstArgKind::Struct(path, inits) => { + self.hash_qpath(path); + for init in *inits { + self.hash_const_arg(init.expr); + } + } ConstArgKind::Infer(..) | ConstArgKind::Error(..) => {}, } } diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs index 9bb0ab70de236..74901cceb0f8d 100644 --- a/src/tools/miri/src/intrinsics/atomic.rs +++ b/src/tools/miri/src/intrinsics/atomic.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::BinOp; -use rustc_middle::ty::AtomicOrdering; +use rustc_middle::ty::{AtomicOrdering, ValTreeKindExt}; use rustc_middle::{mir, ty}; use super::check_intrinsic_arg_count; @@ -31,7 +31,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let get_ord_at = |i: usize| { let ordering = generic_args.const_at(i).to_value(); - ordering.valtree.unwrap_branch()[0].unwrap_leaf().to_atomic_ordering() + ordering.valtree.unwrap_branch()[0].to_value().valtree.unwrap_leaf().to_atomic_ordering() }; fn read_ord(ord: AtomicOrdering) -> AtomicReadOrd { diff --git a/tests/rustdoc/inline_cross/auxiliary/assoc-const-equality.rs b/tests/rustdoc/inline_cross/auxiliary/assoc-const-equality.rs index f6c03d189b5e5..049576396bcf0 100644 --- a/tests/rustdoc/inline_cross/auxiliary/assoc-const-equality.rs +++ b/tests/rustdoc/inline_cross/auxiliary/assoc-const-equality.rs @@ -1,7 +1,7 @@ #![expect(incomplete_features)] #![feature(associated_const_equality, min_generic_const_args)] -pub fn accept(_: impl Trait) {} +pub fn accept(_: impl Trait) {} pub trait Trait { #[type_const] diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs index 2ff5a0353a0a6..adb3e41c23b09 100644 --- a/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs @@ -10,7 +10,7 @@ trait Parent0 { const K: (); } -fn take0(_: impl Trait0) {} +fn take0(_: impl Trait0) {} //~^ ERROR ambiguous associated constant `K` in bounds of `Trait0` trait Trait1: Parent1 + Parent2 {} @@ -23,7 +23,7 @@ trait Parent2 { const C: &'static str; } -fn take1(_: impl Trait1) {} +fn take1(_: impl Trait1) {} //~^ ERROR ambiguous associated constant `C` in bounds of `Trait1` fn main() {} diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr index 3541664d1c6a7..806b2054603d3 100644 --- a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr @@ -7,8 +7,8 @@ LL | const K: (); | ambiguous `K` from `Parent0` | ambiguous `K` from `Parent0` ... -LL | fn take0(_: impl Trait0) {} - | ^^^^^^^^^^ ambiguous associated constant `K` +LL | fn take0(_: impl Trait0) {} + | ^^^^^^^^^^^^^^^^ ambiguous associated constant `K` | = help: consider introducing a new type parameter `T` and adding `where` constraints: where @@ -25,8 +25,8 @@ LL | const C: i32; LL | const C: &'static str; | --------------------- ambiguous `C` from `Parent2` ... -LL | fn take1(_: impl Trait1) {} - | ^^^^^^^ ambiguous associated constant `C` +LL | fn take1(_: impl Trait1) {} + | ^^^^^^^^^^^^^^^^^ ambiguous associated constant `C` error: aborting due to 2 previous errors diff --git a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs index 5232b895803e8..5ad977ec97dcf 100644 --- a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs +++ b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs @@ -18,7 +18,7 @@ trait Trait { fn take( _: impl Trait< < fn(&'a str) -> &'a str as Project>::Out as Discard>::Out, - K = { () } + K = const { () } >, ) {} //~^^^^^ ERROR implementation of `Project` is not general enough diff --git a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr index a0329e2b15d17..f871b097790c7 100644 --- a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr @@ -1,14 +1,14 @@ error: higher-ranked subtype error - --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13 + --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:19 | -LL | K = { () } - | ^^^^^^ +LL | K = const { () } + | ^^^^^^ error: higher-ranked subtype error - --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13 + --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:19 | -LL | K = { () } - | ^^^^^^ +LL | K = const { () } + | ^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` @@ -18,7 +18,7 @@ error: implementation of `Project` is not general enough LL | _: impl Trait< | _____________^ LL | | < fn(&'a str) -> &'a str as Project>::Out as Discard>::Out, -LL | | K = { () } +LL | | K = const { () } LL | | >, | |_____^ implementation of `Project` is not general enough | diff --git a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs index ef8077b9f44a5..f606914222824 100644 --- a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs +++ b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs @@ -21,7 +21,7 @@ trait Trait { fn take( _: impl Trait< fn(&'a str) -> &'a str as Discard>::Out, - K = { () } + K = const { () } >, ) {} diff --git a/tests/ui/associated-consts/assoc-const-eq-const_evaluatable_unchecked.rs b/tests/ui/associated-consts/assoc-const-eq-const_evaluatable_unchecked.rs index 22a03e47b2f76..e88e03eb963ec 100644 --- a/tests/ui/associated-consts/assoc-const-eq-const_evaluatable_unchecked.rs +++ b/tests/ui/associated-consts/assoc-const-eq-const_evaluatable_unchecked.rs @@ -9,12 +9,12 @@ pub trait TraitA { #[type_const] - const K: u8 = 0; + const K: u8 = const { 0 }; } pub trait TraitB {} impl TraitA for () {} -impl TraitB for () where (): TraitA {} +impl TraitB for () where (): TraitA {} fn check() where (): TraitB {} diff --git a/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs b/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs index 1ab93ea596a76..2571af57e66ba 100644 --- a/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs +++ b/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs @@ -8,7 +8,7 @@ trait Trait<'a> { const K: &'a (); } -fn take(_: impl for<'r> Trait<'r, K = { &() }>) {} +fn take(_: impl for<'r> Trait<'r, K = const { &() }>) {} //~^ ERROR the type of the associated constant `K` cannot capture late-bound generic parameters //~| NOTE its type cannot capture the late-bound lifetime parameter `'r` //~| NOTE the late-bound lifetime parameter `'r` is defined here diff --git a/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.stderr b/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.stderr index d6a7eb6cfc7d9..44304443ac542 100644 --- a/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.stderr @@ -1,7 +1,7 @@ error: the type of the associated constant `K` cannot capture late-bound generic parameters --> $DIR/assoc-const-eq-esc-bound-var-in-ty.rs:11:35 | -LL | fn take(_: impl for<'r> Trait<'r, K = { &() }>) {} +LL | fn take(_: impl for<'r> Trait<'r, K = const { &() }>) {} | -- ^ its type cannot capture the late-bound lifetime parameter `'r` | | | the late-bound lifetime parameter `'r` is defined here diff --git a/tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs b/tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs index 0afb95a0b0336..242ad385947aa 100644 --- a/tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs +++ b/tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs @@ -15,31 +15,33 @@ trait Trait<'a, T: 'a + ConstParamTy_, const N: usize> { const K: &'a [T; N]; } -fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} -//~^ ERROR the type of the associated constant `K` must not depend on generic parameters -//~| NOTE its type must not depend on the lifetime parameter `'r` -//~| NOTE the lifetime parameter `'r` is defined here -//~| NOTE `K` has type `&'r [A; Q]` -//~| ERROR the type of the associated constant `K` must not depend on generic parameters -//~| NOTE its type must not depend on the type parameter `A` -//~| NOTE the type parameter `A` is defined here -//~| NOTE `K` has type `&'r [A; Q]` -//~| ERROR the type of the associated constant `K` must not depend on generic parameters -//~| NOTE its type must not depend on the const parameter `Q` -//~| NOTE the const parameter `Q` is defined here -//~| NOTE `K` has type `&'r [A; Q]` +fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>( + //~^ NOTE the lifetime parameter `'r` is defined here + //~| NOTE the type parameter `A` is defined here + //~| NOTE the const parameter `Q` is defined here + _: impl Trait<'r, A, Q, K = const { loop {} }> + //~^ ERROR the type of the associated constant `K` must not depend on generic parameters + //~| NOTE its type must not depend on the lifetime parameter `'r` + //~| NOTE `K` has type `&'r [A; Q]` + //~| ERROR the type of the associated constant `K` must not depend on generic parameters + //~| NOTE its type must not depend on the type parameter `A` + //~| NOTE `K` has type `&'r [A; Q]` + //~| ERROR the type of the associated constant `K` must not depend on generic parameters + //~| NOTE its type must not depend on the const parameter `Q` + //~| NOTE `K` has type `&'r [A; Q]` +) {} trait Project: ConstParamTy_ { #[type_const] const SELF: Self; } -fn take1(_: impl Project) {} +fn take1(_: impl Project) {} //~^ ERROR the type of the associated constant `SELF` must not depend on `impl Trait` //~| NOTE its type must not depend on `impl Trait` //~| NOTE the `impl Trait` is specified here -fn take2>(_: P) {} +fn take2>(_: P) {} //~^ ERROR the type of the associated constant `SELF` must not depend on generic parameters //~| NOTE its type must not depend on the type parameter `P` //~| NOTE the type parameter `P` is defined here @@ -48,7 +50,7 @@ fn take2>(_: P) {} trait Iface<'r>: ConstParamTy_ { //~^ NOTE the lifetime parameter `'r` is defined here //~| NOTE the lifetime parameter `'r` is defined here - type Assoc: Trait<'r, Self, Q, K = { loop {} }> + type Assoc: Trait<'r, Self, Q, K = const { loop {} }> //~^ ERROR the type of the associated constant `K` must not depend on generic parameters //~| ERROR the type of the associated constant `K` must not depend on generic parameters //~| NOTE its type must not depend on the lifetime parameter `'r` diff --git a/tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr b/tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr index 229dd10c0bebf..b742e68044b0c 100644 --- a/tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr @@ -1,42 +1,49 @@ error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:18:77 + --> $DIR/assoc-const-eq-param-in-ty.rs:22:29 | -LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} - | -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r` +LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>( + | -- the lifetime parameter `'r` is defined here +... +LL | _: impl Trait<'r, A, Q, K = const { loop {} }> + | ^ its type must not depend on the lifetime parameter `'r` | = note: `K` has type `&'r [A; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:18:77 + --> $DIR/assoc-const-eq-param-in-ty.rs:22:29 | -LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} - | - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A` +LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>( + | - the type parameter `A` is defined here +... +LL | _: impl Trait<'r, A, Q, K = const { loop {} }> + | ^ its type must not depend on the type parameter `A` | = note: `K` has type `&'r [A; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:18:77 + --> $DIR/assoc-const-eq-param-in-ty.rs:22:29 | -LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} - | - ^ its type must not depend on the const parameter `Q` - | | - | the const parameter `Q` is defined here +LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>( + | - the const parameter `Q` is defined here +... +LL | _: impl Trait<'r, A, Q, K = const { loop {} }> + | ^ its type must not depend on the const parameter `Q` | = note: `K` has type `&'r [A; Q]` error: the type of the associated constant `SELF` must not depend on `impl Trait` - --> $DIR/assoc-const-eq-param-in-ty.rs:37:26 + --> $DIR/assoc-const-eq-param-in-ty.rs:39:26 | -LL | fn take1(_: impl Project) {} - | -------------^^^^------ +LL | fn take1(_: impl Project) {} + | -------------^^^^------------ | | | | | its type must not depend on `impl Trait` | the `impl Trait` is specified here error: the type of the associated constant `SELF` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:42:21 + --> $DIR/assoc-const-eq-param-in-ty.rs:44:21 | -LL | fn take2>(_: P) {} +LL | fn take2>(_: P) {} | - ^^^^ its type must not depend on the type parameter `P` | | | the type parameter `P` is defined here @@ -44,28 +51,28 @@ LL | fn take2>(_: P) {} = note: `SELF` has type `P` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:53:52 | LL | trait Iface<'r>: ConstParamTy_ { | -- the lifetime parameter `'r` is defined here ... -LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> +LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | ^ its type must not depend on the lifetime parameter `'r` | = note: `K` has type `&'r [Self; Q]` error: the type of the associated constant `K` must not depend on `Self` - --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:53:52 | -LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> +LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | ^ its type must not depend on `Self` | = note: `K` has type `&'r [Self; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:53:52 | -LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> +LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | - ^ its type must not depend on the const parameter `Q` | | | the const parameter `Q` is defined here @@ -73,30 +80,30 @@ LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> = note: `K` has type `&'r [Self; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:53:52 | LL | trait Iface<'r>: ConstParamTy_ { | -- the lifetime parameter `'r` is defined here ... -LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> +LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | ^ its type must not depend on the lifetime parameter `'r` | = note: `K` has type `&'r [Self; Q]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: the type of the associated constant `K` must not depend on `Self` - --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:53:52 | -LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> +LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | ^ its type must not depend on `Self` | = note: `K` has type `&'r [Self; Q]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:53:52 | -LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> +LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | - ^ its type must not depend on the const parameter `Q` | | | the const parameter `Q` is defined here diff --git a/tests/ui/associated-consts/assoc-const-eq-supertraits.rs b/tests/ui/associated-consts/assoc-const-eq-supertraits.rs index d9b8a8cd43d7d..3675f73c8cc14 100644 --- a/tests/ui/associated-consts/assoc-const-eq-supertraits.rs +++ b/tests/ui/associated-consts/assoc-const-eq-supertraits.rs @@ -20,6 +20,6 @@ trait SuperSuperTrait { const K: T; } -fn take(_: impl Trait) {} +fn take(_: impl Trait) {} fn main() {} diff --git a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs index 41857eca87de6..d4491c218bf41 100644 --- a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs +++ b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs @@ -21,8 +21,8 @@ trait SuperTrait { const Q: &'static str; } -fn take0(_: impl Trait) {} +fn take0(_: impl Trait) {} -fn take1(_: impl Trait) {} +fn take1(_: impl Trait) {} fn main() {} diff --git a/tests/ui/associated-consts/assoc-const.rs b/tests/ui/associated-consts/assoc-const.rs index 4eed8bba53b1d..b1fa6066e6b34 100644 --- a/tests/ui/associated-consts/assoc-const.rs +++ b/tests/ui/associated-consts/assoc-const.rs @@ -11,13 +11,13 @@ pub struct Bar; impl Foo for Bar { #[type_const] - const N: usize = 3; + const N: usize = const { 3 }; } const TEST:usize = 3; -fn foo>() {} +fn foo>() {} fn main() { foo::() diff --git a/tests/ui/associated-consts/equality-unused-issue-126729.rs b/tests/ui/associated-consts/equality-unused-issue-126729.rs index 35b49314b5f59..3c9edcf634ff9 100644 --- a/tests/ui/associated-consts/equality-unused-issue-126729.rs +++ b/tests/ui/associated-consts/equality-unused-issue-126729.rs @@ -11,10 +11,10 @@ trait Tr { impl Tr for () { #[type_const] - const I: i32 = 1; + const I: i32 = const { 1 }; } -fn foo() -> impl Tr {} +fn foo() -> impl Tr {} trait Tr2 { #[type_const] @@ -25,12 +25,12 @@ trait Tr2 { impl Tr2 for () { #[type_const] - const J: i32 = 1; + const J: i32 = const { 1 }; #[type_const] - const K: i32 = 1; + const K: i32 = const { 1 }; } -fn foo2() -> impl Tr2 {} +fn foo2() -> impl Tr2 {} mod t { pub trait Tr3 { @@ -40,11 +40,11 @@ mod t { impl Tr3 for () { #[type_const] - const L: i32 = 1; + const L: i32 = const { 1 }; } } -fn foo3() -> impl t::Tr3 {} +fn foo3() -> impl t::Tr3 {} fn main() { foo(); diff --git a/tests/ui/associated-consts/issue-102335-const.rs b/tests/ui/associated-consts/issue-102335-const.rs index f9b816fd3bc95..bf0585aec5bc0 100644 --- a/tests/ui/associated-consts/issue-102335-const.rs +++ b/tests/ui/associated-consts/issue-102335-const.rs @@ -2,7 +2,7 @@ #![allow(incomplete_features)] trait T { - type A: S = 34>; + type A: S = const { 34 }>; //~^ ERROR associated item constraints are not allowed here //~| ERROR associated item constraints are not allowed here } diff --git a/tests/ui/associated-consts/issue-102335-const.stderr b/tests/ui/associated-consts/issue-102335-const.stderr index 536e39e5522d7..9533b621990b8 100644 --- a/tests/ui/associated-consts/issue-102335-const.stderr +++ b/tests/ui/associated-consts/issue-102335-const.stderr @@ -1,26 +1,26 @@ error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-const.rs:5:17 | -LL | type A: S = 34>; - | ^^^^^^^^ associated item constraint not allowed here +LL | type A: S = const { 34 }>; + | ^^^^^^^^^^^^^^^^^^ associated item constraint not allowed here | help: consider removing this associated item binding | -LL - type A: S = 34>; -LL + type A: S; +LL - type A: S = const { 34 }>; +LL + type A: S; | error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-const.rs:5:17 | -LL | type A: S = 34>; - | ^^^^^^^^ associated item constraint not allowed here +LL | type A: S = const { 34 }>; + | ^^^^^^^^^^^^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider removing this associated item binding | -LL - type A: S = 34>; -LL + type A: S; +LL - type A: S = const { 34 }>; +LL + type A: S; | error: aborting due to 2 previous errors diff --git a/tests/ui/associated-consts/issue-110933.rs b/tests/ui/associated-consts/issue-110933.rs index 0284369f4d658..731ff1564ce26 100644 --- a/tests/ui/associated-consts/issue-110933.rs +++ b/tests/ui/associated-consts/issue-110933.rs @@ -10,7 +10,7 @@ pub trait Trait { pub fn foo< T: Trait< - ASSOC = { + ASSOC = const { let a = 10_usize; let b: &'_ usize = &a; *b diff --git a/tests/ui/associated-consts/projection-unspecified-but-bounded.rs b/tests/ui/associated-consts/projection-unspecified-but-bounded.rs index 7f3304f076561..35c1d4bfc048d 100644 --- a/tests/ui/associated-consts/projection-unspecified-but-bounded.rs +++ b/tests/ui/associated-consts/projection-unspecified-but-bounded.rs @@ -8,7 +8,7 @@ pub trait TraitWAssocConst { const A: usize; } -fn foo>() {} +fn foo>() {} fn bar() { foo::(); diff --git a/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr b/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr index 232b15b7e981a..c1af0d2e78369 100644 --- a/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr +++ b/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr @@ -9,8 +9,8 @@ LL | foo::(); note: required by a bound in `foo` --> $DIR/projection-unspecified-but-bounded.rs:11:28 | -LL | fn foo>() {} - | ^^^^^^ required by this bound in `foo` +LL | fn foo>() {} + | ^^^^^^^^^^^^^^^^ required by this bound in `foo` error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/const-projection-err.gce.stderr b/tests/ui/associated-type-bounds/const-projection-err.gce.stderr deleted file mode 100644 index 9ad851d188d37..0000000000000 --- a/tests/ui/associated-type-bounds/const-projection-err.gce.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0271]: type mismatch resolving `::A == 1` - --> $DIR/const-projection-err.rs:16:11 - | -LL | foo::(); - | ^ expected `0`, found `1` - | -note: required by a bound in `foo` - --> $DIR/const-projection-err.rs:13:28 - | -LL | fn foo>() {} - | ^^^^^ required by this bound in `foo` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-type-bounds/const-projection-err.rs b/tests/ui/associated-type-bounds/const-projection-err.rs index 80845ec3ee86e..381eed13f5351 100644 --- a/tests/ui/associated-type-bounds/const-projection-err.rs +++ b/tests/ui/associated-type-bounds/const-projection-err.rs @@ -1,18 +1,14 @@ -//@ revisions: stock gce - #![feature(associated_const_equality, min_generic_const_args)] #![allow(incomplete_features)] -#![cfg_attr(gce, feature(generic_const_exprs))] - trait TraitWAssocConst { #[type_const] const A: usize; } -fn foo>() {} +fn foo>() {} -fn bar>() { +fn bar>() { foo::(); //~^ ERROR type mismatch resolving `::A == 1` } diff --git a/tests/ui/associated-type-bounds/const-projection-err.stderr b/tests/ui/associated-type-bounds/const-projection-err.stderr new file mode 100644 index 0000000000000..2de4f62d1b031 --- /dev/null +++ b/tests/ui/associated-type-bounds/const-projection-err.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving `::A == 1` + --> $DIR/const-projection-err.rs:12:11 + | +LL | foo::(); + | ^ expected `1`, found `0` + | + = note: expected constant `1` + found constant `0` +note: required by a bound in `foo` + --> $DIR/const-projection-err.rs:9:28 + | +LL | fn foo>() {} + | ^^^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.rs b/tests/ui/associated-type-bounds/duplicate-bound-err.rs index 72c1ab559bdf0..639d8c64acec8 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.rs +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.rs @@ -61,7 +61,7 @@ impl Trait for () { type Gat = (); #[type_const] - const ASSOC: i32 = 3; + const ASSOC: i32 = const { 3 }; fn foo() {} } @@ -70,7 +70,7 @@ impl Trait for u32 { type Gat = (); #[type_const] - const ASSOC: i32 = 4; + const ASSOC: i32 = const { 4 }; fn foo() -> u32 { 42 @@ -79,9 +79,11 @@ impl Trait for u32 { fn uncallable(_: impl Iterator) {} -fn uncallable_const(_: impl Trait) {} +fn uncallable_const(_: impl Trait) {} -fn uncallable_rtn(_: impl Trait, foo(..): Trait>) {} +fn uncallable_rtn( + _: impl Trait, foo(..): Trait> +) {} type MustFail = dyn Iterator; //~^ ERROR [E0719] @@ -92,14 +94,14 @@ trait Trait2 { const ASSOC: u32; } -type MustFail2 = dyn Trait2; +type MustFail2 = dyn Trait2; //~^ ERROR [E0719] //~| ERROR conflicting associated type bounds type MustFail3 = dyn Iterator; //~^ ERROR [E0719] -type MustFail4 = dyn Trait2; +type MustFail4 = dyn Trait2; //~^ ERROR [E0719] trait Trait3 { diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr index a54425c3a2956..92587d377b09e 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr @@ -100,7 +100,7 @@ LL | iter::empty::() | ----------------------- return type was inferred to be `std::iter::Empty` here error[E0271]: expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:110:17 + --> $DIR/duplicate-bound-err.rs:112:17 | LL | fn foo() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` @@ -109,7 +109,7 @@ LL | [2u32].into_iter() | ------------------ return type was inferred to be `std::array::IntoIter` here error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate-bound-err.rs:86:42 + --> $DIR/duplicate-bound-err.rs:88:42 | LL | type MustFail = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -117,7 +117,7 @@ LL | type MustFail = dyn Iterator; | `Item` bound here first error: conflicting associated type bounds for `Item` - --> $DIR/duplicate-bound-err.rs:86:17 + --> $DIR/duplicate-bound-err.rs:88:17 | LL | type MustFail = dyn Iterator; | ^^^^^^^^^^^^^----------^^----------^ @@ -126,24 +126,24 @@ LL | type MustFail = dyn Iterator; | `Item` is specified to be `i32` here error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified - --> $DIR/duplicate-bound-err.rs:95:43 + --> $DIR/duplicate-bound-err.rs:97:53 | -LL | type MustFail2 = dyn Trait2; - | ------------ ^^^^^^^^^^^^ re-bound here +LL | type MustFail2 = dyn Trait2; + | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^ re-bound here | | | `ASSOC` bound here first error: conflicting associated type bounds for `ASSOC` - --> $DIR/duplicate-bound-err.rs:95:18 + --> $DIR/duplicate-bound-err.rs:97:18 | -LL | type MustFail2 = dyn Trait2; - | ^^^^^^^^^^^------------^^------------^ - | | | - | | `ASSOC` is specified to be `4` here +LL | type MustFail2 = dyn Trait2; + | ^^^^^^^^^^^----------------------^^----------------------^ + | | | + | | `ASSOC` is specified to be `4` here | `ASSOC` is specified to be `3` here error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate-bound-err.rs:99:43 + --> $DIR/duplicate-bound-err.rs:101:43 | LL | type MustFail3 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -151,27 +151,27 @@ LL | type MustFail3 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified - --> $DIR/duplicate-bound-err.rs:102:43 + --> $DIR/duplicate-bound-err.rs:104:53 | -LL | type MustFail4 = dyn Trait2; - | ------------ ^^^^^^^^^^^^ re-bound here +LL | type MustFail4 = dyn Trait2; + | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^ re-bound here | | | `ASSOC` bound here first error[E0271]: expected `impl Iterator` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:110:17 + --> $DIR/duplicate-bound-err.rs:112:17 | LL | fn foo() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` | note: required by a bound in `Trait3::foo::{anon_assoc#0}` - --> $DIR/duplicate-bound-err.rs:106:31 + --> $DIR/duplicate-bound-err.rs:108:31 | LL | fn foo() -> impl Iterator; | ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}` error[E0271]: expected `Empty` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:118:16 + --> $DIR/duplicate-bound-err.rs:120:16 | LL | uncallable(iter::empty::()); | ---------- ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` @@ -185,7 +185,7 @@ LL | fn uncallable(_: impl Iterator) {} | ^^^^^^^^^^ required by this bound in `uncallable` error[E0271]: expected `Empty` to be an iterator that yields `u32`, but it yields `i32` - --> $DIR/duplicate-bound-err.rs:119:16 + --> $DIR/duplicate-bound-err.rs:121:16 | LL | uncallable(iter::empty::()); | ---------- ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `i32` @@ -199,7 +199,7 @@ LL | fn uncallable(_: impl Iterator) {} | ^^^^^^^^^^ required by this bound in `uncallable` error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4` - --> $DIR/duplicate-bound-err.rs:120:22 + --> $DIR/duplicate-bound-err.rs:122:22 | LL | uncallable_const(()); | ---------------- ^^ expected `4`, found `3` @@ -209,13 +209,13 @@ LL | uncallable_const(()); = note: expected constant `4` found constant `3` note: required by a bound in `uncallable_const` - --> $DIR/duplicate-bound-err.rs:82:46 + --> $DIR/duplicate-bound-err.rs:82:56 | -LL | fn uncallable_const(_: impl Trait) {} - | ^^^^^^^^^ required by this bound in `uncallable_const` +LL | fn uncallable_const(_: impl Trait) {} + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable_const` error[E0271]: type mismatch resolving `::ASSOC == 3` - --> $DIR/duplicate-bound-err.rs:121:22 + --> $DIR/duplicate-bound-err.rs:123:22 | LL | uncallable_const(4u32); | ---------------- ^^^^ expected `3`, found `4` @@ -227,11 +227,11 @@ LL | uncallable_const(4u32); note: required by a bound in `uncallable_const` --> $DIR/duplicate-bound-err.rs:82:35 | -LL | fn uncallable_const(_: impl Trait) {} - | ^^^^^^^^^ required by this bound in `uncallable_const` +LL | fn uncallable_const(_: impl Trait) {} + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable_const` error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4` - --> $DIR/duplicate-bound-err.rs:122:20 + --> $DIR/duplicate-bound-err.rs:124:20 | LL | uncallable_rtn(()); | -------------- ^^ expected `4`, found `3` @@ -241,13 +241,15 @@ LL | uncallable_rtn(()); = note: expected constant `4` found constant `3` note: required by a bound in `uncallable_rtn` - --> $DIR/duplicate-bound-err.rs:84:75 + --> $DIR/duplicate-bound-err.rs:85:71 | -LL | fn uncallable_rtn(_: impl Trait, foo(..): Trait>) {} - | ^^^^^^^^^ required by this bound in `uncallable_rtn` +LL | fn uncallable_rtn( + | -------------- required by a bound in this function +LL | _: impl Trait, foo(..): Trait> + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable_rtn` error[E0271]: type mismatch resolving `::ASSOC == 3` - --> $DIR/duplicate-bound-err.rs:123:20 + --> $DIR/duplicate-bound-err.rs:125:20 | LL | uncallable_rtn(17u32); | -------------- ^^^^^ expected `3`, found `4` @@ -257,10 +259,12 @@ LL | uncallable_rtn(17u32); = note: expected constant `3` found constant `4` note: required by a bound in `uncallable_rtn` - --> $DIR/duplicate-bound-err.rs:84:48 + --> $DIR/duplicate-bound-err.rs:85:34 | -LL | fn uncallable_rtn(_: impl Trait, foo(..): Trait>) {} - | ^^^^^^^^^ required by this bound in `uncallable_rtn` +LL | fn uncallable_rtn( + | -------------- required by a bound in this function +LL | _: impl Trait, foo(..): Trait> + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable_rtn` error: aborting due to 25 previous errors diff --git a/tests/ui/associated-type-bounds/duplicate-bound.rs b/tests/ui/associated-type-bounds/duplicate-bound.rs index 3f40e429260f0..d185691d95fcb 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound.rs +++ b/tests/ui/associated-type-bounds/duplicate-bound.rs @@ -199,7 +199,7 @@ impl Trait for () { type Gat = (); #[type_const] - const ASSOC: i32 = 3; + const ASSOC: i32 = const { 3 }; fn foo() {} } @@ -220,11 +220,13 @@ fn uncallable(_: impl Iterator) {} fn callable(_: impl Iterator) {} -fn uncallable_const(_: impl Trait) {} +fn uncallable_const(_: impl Trait) {} -fn callable_const(_: impl Trait) {} +fn callable_const(_: impl Trait) {} -fn uncallable_rtn(_: impl Trait, foo(..): Trait>) {} +fn uncallable_rtn( + _: impl Trait, foo(..): Trait> +) {} fn callable_rtn(_: impl Trait) {} diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 26ee89dd7b3be..90affb2c8757e 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -148,7 +148,7 @@ struct Test; trait Hey { #[type_const = 1] //~^ ERROR malformed - const HEY: usize = 5; + const HEY: usize = const { 5 }; } struct Empty; diff --git a/tests/ui/const-generics/associated_const_equality/coherence.rs b/tests/ui/const-generics/associated_const_equality/coherence.rs index fb5f255c1dc4d..7fb4f055afb8c 100644 --- a/tests/ui/const-generics/associated_const_equality/coherence.rs +++ b/tests/ui/const-generics/associated_const_equality/coherence.rs @@ -7,12 +7,12 @@ pub trait IsVoid { } impl IsVoid for () { #[type_const] - const IS_VOID: bool = true; + const IS_VOID: bool = const { true }; } pub trait Maybe {} impl Maybe for () {} -impl Maybe for () where (): IsVoid {} +impl Maybe for () where (): IsVoid {} //~^ ERROR conflicting implementations of trait `Maybe` for type `()` fn main() {} diff --git a/tests/ui/const-generics/associated_const_equality/coherence.stderr b/tests/ui/const-generics/associated_const_equality/coherence.stderr index 23d6495a16a44..592e13397b326 100644 --- a/tests/ui/const-generics/associated_const_equality/coherence.stderr +++ b/tests/ui/const-generics/associated_const_equality/coherence.stderr @@ -3,8 +3,8 @@ error[E0119]: conflicting implementations of trait `Maybe` for type `()` | LL | impl Maybe for () {} | ----------------- first implementation here -LL | impl Maybe for () where (): IsVoid {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` +LL | impl Maybe for () where (): IsVoid {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` error: aborting due to 1 previous error 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 index 3973c7af15b49..05c798f7ac358 100644 --- 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 @@ -16,7 +16,7 @@ impl Foo for () { const ASSOC: u32 = N; } -fn bar = 10>>() {} +fn bar = const { 10 }>>() {} fn main() { bar::<_, ()>(); diff --git a/tests/ui/const-generics/associated_const_equality/mismatched-types-with-generic-in-ace.rs b/tests/ui/const-generics/associated_const_equality/mismatched-types-with-generic-in-ace.rs index 33afa7e3228ee..ac5de6719e8ba 100644 --- a/tests/ui/const-generics/associated_const_equality/mismatched-types-with-generic-in-ace.rs +++ b/tests/ui/const-generics/associated_const_equality/mismatched-types-with-generic-in-ace.rs @@ -15,6 +15,6 @@ fn bar = { N }>>() {} //~^ ERROR: the constant `N` is not of type `u32` fn main() { - bar::<10_u64, ()>(); + bar::(); //~^ ERROR: the constant `10` is not of type `u32` } diff --git a/tests/ui/const-generics/associated_const_equality/mismatched-types-with-generic-in-ace.stderr b/tests/ui/const-generics/associated_const_equality/mismatched-types-with-generic-in-ace.stderr index c2fb7faa3a3a0..094dd2598f018 100644 --- a/tests/ui/const-generics/associated_const_equality/mismatched-types-with-generic-in-ace.stderr +++ b/tests/ui/const-generics/associated_const_equality/mismatched-types-with-generic-in-ace.stderr @@ -13,8 +13,8 @@ LL | const ASSOC: u32; error: the constant `10` is not of type `u32` --> $DIR/mismatched-types-with-generic-in-ace.rs:18:5 | -LL | bar::<10_u64, ()>(); - | ^^^^^^^^^^^^^^^^^^^ expected `u32`, found `u64` +LL | bar::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `u64` | note: required by a const generic parameter in `Foo::ASSOC` --> $DIR/mismatched-types-with-generic-in-ace.rs:6:17 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 index edadcd7c80ed2..f28f3f694ff3e 100644 --- a/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.rs +++ b/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.rs @@ -12,7 +12,7 @@ impl AssocConst for (T,) { trait Trait {} -impl Trait for () where (U,): AssocConst {} +impl Trait for () where (U,): AssocConst {} //~^ ERROR associated const equality is incomplete //~| ERROR the type parameter `U` is not constrained by the impl trait 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 index 4106c500215b9..092faff935115 100644 --- a/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.stderr +++ b/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.stderr @@ -1,8 +1,8 @@ error[E0658]: associated const equality is incomplete --> $DIR/unconstrained_impl_param.rs:15:45 | -LL | impl Trait for () where (U,): AssocConst {} - | ^^^^^^^^^ +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 @@ -11,7 +11,7 @@ LL | impl Trait for () where (U,): AssocConst {} 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 {} +LL | impl Trait for () where (U,): AssocConst {} | ^ unconstrained type parameter error[E0282]: type annotations needed diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.rs b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs index bb5bdb8d7c4cf..b17217f8ff1b1 100644 --- a/tests/ui/const-generics/mgca/bad-type_const-syntax.rs +++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs @@ -10,7 +10,8 @@ struct S; impl Tr for S { #[type_const] //~^ ERROR experimental - const N: usize = 0; + const N: usize = const { 0 }; + //~^ ERROR: unbraced const blocks as const args are experimental } fn main() {} diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr index df442c22241b9..ac9e8069b6c6b 100644 --- a/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr +++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr @@ -1,3 +1,13 @@ +error[E0658]: unbraced const blocks as const args are experimental + --> $DIR/bad-type_const-syntax.rs:13:28 + | +LL | const N: usize = const { 0 }; + | ^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` 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[E0658]: the `#[type_const]` attribute is an experimental feature --> $DIR/bad-type_const-syntax.rs:2:5 | @@ -27,7 +37,7 @@ LL | #[type_const()] | | didn't expect any arguments here | help: must be of the form: `#[type_const]` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0565, E0658. For more information about an error, try `rustc --explain E0565`. diff --git a/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs index 37f9c31feaa55..c7b08be0f4ead 100644 --- a/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs +++ b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs @@ -16,11 +16,11 @@ pub struct S; impl Tr for S { #[type_const] - const N1: usize = 0; + const N1: usize = const { 0 }; #[type_const] - const N2: usize = 1; + const N2: usize = const { 1 }; #[type_const] - const N3: usize = 2; + const N3: usize = const { 2 }; } fn main() {} diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.rs b/tests/ui/const-generics/mgca/explicit_anon_consts.rs new file mode 100644 index 0000000000000..c573a6bad3bed --- /dev/null +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.rs @@ -0,0 +1,71 @@ +#![feature(associated_const_equality, generic_const_items, min_generic_const_args)] +#![expect(incomplete_features)] + +struct Foo; + +type Adt1 = Foo; +type Adt2 = Foo<{ N }>; +type Adt3 = Foo; +//~^ ERROR: generic parameters may not be used in const operations +//~^^ ERROR generic parameters may not be used in const operations +type Adt4 = Foo<{ 1 + 1 }>; +//~^ ERROR: complex const arguments must be placed inside of a `const` block +type Adt5 = Foo; + +type Arr = [(); N]; +type Arr2 = [(); { N }]; +type Arr3 = [(); const { N }]; +//~^ ERROR: generic parameters may not be used in const operations +type Arr4 = [(); 1 + 1]; +//~^ ERROR: complex const arguments must be placed inside of a `const` block +type Arr5 = [(); const { 1 + 1 }]; + +fn repeats() { + let _1 = [(); N]; + let _2 = [(); { N }]; + let _3 = [(); const { N }]; + //~^ ERROR: generic parameters may not be used in const operations + let _4 = [(); 1 + 1]; + //~^ ERROR: complex const arguments must be placed inside of a `const` block + let _5 = [(); const { 1 + 1 }]; +} + +#[type_const] +const ITEM1: usize = N; +#[type_const] +const ITEM2: usize = { N }; +#[type_const] +const ITEM3: usize = const { N }; +//~^ ERROR: generic parameters may not be used in const operations +#[type_const] +const ITEM4: usize = { 1 + 1 }; +//~^ ERROR: complex const arguments must be placed inside of a `const` block +#[type_const] +const ITEM5: usize = const { 1 + 1}; + +trait Trait { + #[type_const] + const ASSOC: usize; +} + +fn ace_bounds< + const N: usize, + // We skip the T1 case because it doesn't resolve + // T1: Trait, + T2: Trait, + T3: Trait, + //~^ ERROR: generic parameters may not be used in const operations + T4: Trait, + //~^ ERROR: complex const arguments must be placed inside of a `const` block + T5: Trait, +>() {} + +struct Default1; +struct Default2; +struct Default3; +//~^ ERROR: generic parameters may not be used in const operations +struct Default4; +//~^ ERROR: complex const arguments must be placed inside of a `const` block +struct Default5; + +fn main() {} diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr new file mode 100644 index 0000000000000..9cb75209f2b05 --- /dev/null +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr @@ -0,0 +1,82 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/explicit_anon_consts.rs:11:33 + | +LL | type Adt4 = Foo<{ 1 + 1 }>; + | ^^^^^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/explicit_anon_consts.rs:19:34 + | +LL | type Arr4 = [(); 1 + 1]; + | ^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/explicit_anon_consts.rs:28:19 + | +LL | let _4 = [(); 1 + 1]; + | ^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/explicit_anon_consts.rs:41:38 + | +LL | const ITEM4: usize = { 1 + 1 }; + | ^^^^^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/explicit_anon_consts.rs:58:23 + | +LL | T4: Trait, + | ^^^^^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/explicit_anon_consts.rs:67:50 + | +LL | struct Default4; + | ^^^^^^^^^ + +error: generic parameters may not be used in const operations + --> $DIR/explicit_anon_consts.rs:8:41 + | +LL | type Adt3 = Foo; + | ^ + +error: generic parameters may not be used in const operations + --> $DIR/explicit_anon_consts.rs:17:42 + | +LL | type Arr3 = [(); const { N }]; + | ^ + +error: generic parameters may not be used in const operations + --> $DIR/explicit_anon_consts.rs:38:46 + | +LL | const ITEM3: usize = const { N }; + | ^ + +error: generic parameters may not be used in const operations + --> $DIR/explicit_anon_consts.rs:56:31 + | +LL | T3: Trait, + | ^ + +error: generic parameters may not be used in const operations + --> $DIR/explicit_anon_consts.rs:65:58 + | +LL | struct Default3; + | ^ + +error: generic parameters may not be used in const operations + --> $DIR/explicit_anon_consts.rs:26:27 + | +LL | let _3 = [(); const { N }]; + | ^ + +error: generic parameters may not be used in const operations + --> $DIR/explicit_anon_consts.rs:8:41 + | +LL | type Adt3 = Foo; + | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 13 previous errors + diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index 8d2eae71d330d..3775d30943fd9 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -2,7 +2,7 @@ #![feature(min_generic_const_args)] #[type_const] -const FREE: u32 = 5_usize; +const FREE: u32 = const { 5_usize }; //~^ ERROR mismatched types #[type_const] @@ -16,7 +16,7 @@ trait Tr { impl Tr for () { #[type_const] - const N: usize = false; + const N: usize = const { false }; //~^ ERROR mismatched types } diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr index 4029bb7b6bff2..3501eacb1acaf 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -5,22 +5,22 @@ LL | const FREE2: isize = FREE; | ^^^^^^^^^^^^^^^^^^ expected `isize`, found `u32` error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:5:19 + --> $DIR/type_const-mismatched-types.rs:5:27 | -LL | const FREE: u32 = 5_usize; - | ^^^^^^^ expected `u32`, found `usize` +LL | const FREE: u32 = const { 5_usize }; + | ^^^^^^^ expected `u32`, found `usize` | help: change the type of the numeric literal from `usize` to `u32` | -LL - const FREE: u32 = 5_usize; -LL + const FREE: u32 = 5_u32; +LL - const FREE: u32 = const { 5_usize }; +LL + const FREE: u32 = const { 5_u32 }; | error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:19:22 + --> $DIR/type_const-mismatched-types.rs:19:30 | -LL | const N: usize = false; - | ^^^^^ expected `usize`, found `bool` +LL | const N: usize = const { false }; + | ^^^^^ expected `usize`, found `bool` error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-not-constparamty.rs b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs index 27b446e6a40d2..11db82187b847 100644 --- a/tests/ui/const-generics/mgca/type_const-not-constparamty.rs +++ b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs @@ -4,9 +4,9 @@ struct S; // FIXME(mgca): need support for ctors without anon const -// (we use double-braces to trigger an anon const here) +// (we use a const-block to trigger an anon const here) #[type_const] -const FREE: S = { { S } }; +const FREE: S = const { S }; //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter trait Tr { @@ -17,9 +17,9 @@ trait Tr { impl Tr for S { // FIXME(mgca): need support for ctors without anon const - // (we use double-braces to trigger an anon const here) + // (we use a const-block to trigger an anon const here) #[type_const] - const N: S = { { S } }; + const N: S = const { S }; //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter } diff --git a/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr b/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr index 6b13917a95cd1..d07bbde1e62e7 100644 --- a/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr +++ b/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr @@ -1,7 +1,7 @@ error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter --> $DIR/type_const-not-constparamty.rs:9:13 | -LL | const FREE: S = { { S } }; +LL | const FREE: S = const { S }; | ^ | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct @@ -13,7 +13,7 @@ LL | struct S; error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter --> $DIR/type_const-not-constparamty.rs:22:14 | -LL | const N: S = { { S } }; +LL | const N: S = const { S }; | ^ | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs index d38d5ab7a59f8..a1008fae9d16d 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs @@ -2,10 +2,11 @@ #![feature(min_generic_const_args, generic_const_items)] #[type_const] -const FREE1: usize = std::mem::size_of::(); +const FREE1: usize = const { std::mem::size_of::() }; //~^ ERROR generic parameters may not be used in const operations +//~^^ ERROR generic parameters may not be used in const operations #[type_const] -const FREE2: usize = I + 1; +const FREE2: usize = const { I + 1 }; //~^ ERROR generic parameters may not be used in const operations pub trait Tr { @@ -21,13 +22,13 @@ pub struct S; impl Tr for S { #[type_const] - const N1: usize = std::mem::size_of::(); + const N1: usize = const { std::mem::size_of::() }; //~^ ERROR generic parameters may not be used in const operations #[type_const] - const N2: usize = I + 1; + const N2: usize = const { I + 1 }; //~^ ERROR generic parameters may not be used in const operations #[type_const] - const N3: usize = 2 & X; + const N3: usize = const { 2 & X }; //~^ ERROR generic parameters may not be used in const operations } diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr index 76638f27e96cf..c77be158d0ef7 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr @@ -1,47 +1,40 @@ error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic-expr.rs:5:45 + --> $DIR/type_const-on-generic-expr.rs:5:53 | -LL | const FREE1: usize = std::mem::size_of::(); - | ^ cannot perform const operation using `T` - | - = note: type parameters may not be used in const expressions - = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions +LL | const FREE1: usize = const { std::mem::size_of::() }; + | ^ error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic-expr.rs:8:38 - | -LL | const FREE2: usize = I + 1; - | ^ cannot perform const operation using `I` + --> $DIR/type_const-on-generic-expr.rs:9:46 | - = help: const parameters may only be used as standalone arguments here, i.e. `I` - = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions +LL | const FREE2: usize = const { I + 1 }; + | ^ error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic-expr.rs:24:46 - | -LL | const N1: usize = std::mem::size_of::(); - | ^ cannot perform const operation using `T` + --> $DIR/type_const-on-generic-expr.rs:25:54 | - = note: type parameters may not be used in const expressions - = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions +LL | const N1: usize = const { std::mem::size_of::() }; + | ^ error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic-expr.rs:27:39 + --> $DIR/type_const-on-generic-expr.rs:28:47 | -LL | const N2: usize = I + 1; - | ^ cannot perform const operation using `I` +LL | const N2: usize = const { I + 1 }; + | ^ + +error: generic parameters may not be used in const operations + --> $DIR/type_const-on-generic-expr.rs:31:35 | - = help: const parameters may only be used as standalone arguments here, i.e. `I` - = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions +LL | const N3: usize = const { 2 & X }; + | ^ error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic-expr.rs:30:27 + --> $DIR/type_const-on-generic-expr.rs:5:53 | -LL | const N3: usize = 2 & X; - | ^ cannot perform const operation using `X` +LL | const FREE1: usize = const { std::mem::size_of::() }; + | ^ | - = help: const parameters may only be used as standalone arguments here, i.e. `X` - = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl.rs b/tests/ui/const-generics/mgca/type_const-only-in-impl.rs index ae4a0004232b8..21719343d533b 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl.rs @@ -9,12 +9,12 @@ struct GoodS; impl BadTr for GoodS { #[type_const] - const NUM: usize = 84; + const NUM: usize = const { 84 }; } fn accept_bad_tr>(_x: &T) {} //~^ ERROR use of trait associated const without `#[type_const]` fn main() { - accept_bad_tr::<84, _>(&GoodS); + accept_bad_tr::(&GoodS); } diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs new file mode 100644 index 0000000000000..588fa2f913b63 --- /dev/null +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs @@ -0,0 +1,42 @@ +#![feature(adt_const_params)] + +#[derive(Eq, PartialEq, std::marker::ConstParamTy)] +struct Inner; + +struct Foo< + const PARAM_TY: Inner, + //~^ ERROR: unbraced const blocks as const args are experimental + const DEFAULT: usize = const { 1 }, + //~^ ERROR: unbraced const blocks as const args are experimental +>; + +type Array = [(); const { 1 }]; +type NormalTy = Inner; + //~^ ERROR: unbraced const blocks as const args are experimental + +fn repeat() { + [1_u8; const { 1 }]; +} + +fn body_ty() { + let _: Inner; + //~^ ERROR: unbraced const blocks as const args are experimental +} + +fn generic() { + if false { + generic::(); + //~^ ERROR: unbraced const blocks as const args are experimental + } +} + +const NON_TYPE_CONST: usize = const { 1 }; + +#[type_const] +//~^ ERROR: the `#[type_const]` attribute is an experimental feature +const TYPE_CONST: usize = const { 1 }; +//~^ ERROR: unbraced const blocks as const args are experimental + +static STATIC: usize = const { 1 }; + +fn main() {} diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr new file mode 100644 index 0000000000000..30509ddf9b467 --- /dev/null +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr @@ -0,0 +1,73 @@ +error[E0658]: unbraced const blocks as const args are experimental + --> $DIR/unbraced_const_block_const_arg_gated.rs:7:33 + | +LL | const PARAM_TY: Inner, + | ^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` 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[E0658]: unbraced const blocks as const args are experimental + --> $DIR/unbraced_const_block_const_arg_gated.rs:9:34 + | +LL | const DEFAULT: usize = const { 1 }, + | ^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` 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[E0658]: unbraced const blocks as const args are experimental + --> $DIR/unbraced_const_block_const_arg_gated.rs:14:29 + | +LL | type NormalTy = Inner; + | ^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` 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[E0658]: unbraced const blocks as const args are experimental + --> $DIR/unbraced_const_block_const_arg_gated.rs:22:24 + | +LL | let _: Inner; + | ^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` 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[E0658]: unbraced const blocks as const args are experimental + --> $DIR/unbraced_const_block_const_arg_gated.rs:28:25 + | +LL | generic::(); + | ^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` 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[E0658]: unbraced const blocks as const args are experimental + --> $DIR/unbraced_const_block_const_arg_gated.rs:37:33 + | +LL | const TYPE_CONST: usize = const { 1 }; + | ^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` 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[E0658]: the `#[type_const]` attribute is an experimental feature + --> $DIR/unbraced_const_block_const_arg_gated.rs:35:1 + | +LL | #[type_const] + | ^^^^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` 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: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/mgca/using-fnptr-as-type_const.rs b/tests/ui/const-generics/mgca/using-fnptr-as-type_const.rs index 554e078ccd49c..d97b3a9f09294 100644 --- a/tests/ui/const-generics/mgca/using-fnptr-as-type_const.rs +++ b/tests/ui/const-generics/mgca/using-fnptr-as-type_const.rs @@ -9,6 +9,6 @@ trait Trait { //~^ ERROR using function pointers as const generic parameters is forbidden } -fn take(_: impl Trait) {} +fn take(_: impl Trait) {} fn main() {} diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs index 7f4926fa2b71f..a72aaedb980e0 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs @@ -9,12 +9,12 @@ impl Pins for NoPin {} pub trait PinA { #[type_const] - const A: &'static () = &(); + const A: &'static () = const { &() }; } pub trait Pins {} -impl Pins for T where T: PinA {} +impl Pins for T where T: PinA {} //~^ ERROR conflicting implementations of trait `Pins<_>` for type `NoPin` pub fn main() {} diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr index 34546349592f5..f57fd74ad99df 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr @@ -4,8 +4,8 @@ error[E0119]: conflicting implementations of trait `Pins<_>` for type `NoPin` LL | impl Pins for NoPin {} | --------------------------- first implementation here ... -LL | impl Pins for T where T: PinA {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `NoPin` +LL | impl Pins for T where T: PinA {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `NoPin` | = note: downstream crates may implement trait `PinA<_>` for type `NoPin` diff --git a/tests/ui/generic-const-items/associated-const-equality.rs b/tests/ui/generic-const-items/associated-const-equality.rs index 6f5d4985ae539..1bf68786e5b03 100644 --- a/tests/ui/generic-const-items/associated-const-equality.rs +++ b/tests/ui/generic-const-items/associated-const-equality.rs @@ -17,19 +17,19 @@ impl Owner for () { #[type_const] const C: u32 = N; #[type_const] - const K: u32 = 99 + 1; + const K: u32 = const { 99 + 1 }; // FIXME(mgca): re-enable once we properly support ctors and generics on paths // #[type_const] // const Q: Maybe = Maybe::Nothing; } fn take0(_: impl Owner = { N }>) {} -fn take1(_: impl Owner = 100>) {} +fn take1(_: impl Owner = const { 100 }>) {} // FIXME(mgca): re-enable once we properly support ctors and generics on paths // fn take2(_: impl Owner = { Maybe::Just(()) }>) {} fn main() { - take0::<128>(()); + take0::(()); take1(()); } diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs index edea6f75444f4..07d729c4136c3 100644 --- a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs @@ -10,11 +10,11 @@ pub trait IsVoid { } impl IsVoid for T { #[type_const] - default const IS_VOID: bool = false; + default const IS_VOID: bool = const { false }; } pub trait NotVoid {} -impl NotVoid for T where T: IsVoid + ?Sized {} +impl NotVoid for T where T: IsVoid + ?Sized {} pub trait Maybe {} impl Maybe for T {} diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr index 1a0563b469c1e..a96876a2c25a1 100644 --- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr +++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr @@ -12,7 +12,7 @@ LL | struct ExplicitlyPadded(Box); error[E0391]: cycle detected when computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` | = note: ...which immediately requires computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` again - = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::TransmuteFrom` + = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::TransmuteFrom` = 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: aborting due to 2 previous errors