From 71f8aed510c563cc2d96405df51b410783be75c0 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 29 Jun 2024 21:45:22 -0700 Subject: [PATCH 01/10] Add `current_def_id_parent` to `LoweringContext` This is needed to track anon const parents properly once we implement `ConstArgKind::Path` (which requires moving anon const def-creation outside of `DefCollector`): Why do we need this in addition to [`Self::current_hir_id_owner`]? Currently (as of June 2024), anonymous constants are not HIR owners; however, they do get their own DefIds. Some of these DefIds have to be created during AST lowering, rather than def collection, because we can't tell until after name resolution whether an anonymous constant will end up instead being a [`rustc_hir::ConstArgKind::Path`]. However, to compute which generics are available to an anonymous constant nested inside another, we need to make sure that the parent is recorded as the parent anon const, not the enclosing item. So we need to track parent defs differently from HIR owners, since they will be finer-grained in the case of anon consts. --- compiler/rustc_ast_lowering/src/asm.rs | 4 ++-- compiler/rustc_ast_lowering/src/expr.rs | 10 ++------ compiler/rustc_ast_lowering/src/lib.rs | 32 ++++++++++++++++++++----- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 666e7763e6276..4d4a6fa8a6004 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -222,10 +222,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; // Wrap the expression in an AnonConst. - let parent_def_id = self.current_hir_id_owner; + let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); self.create_def( - parent_def_id.def_id, + parent_def_id, node_id, kw::Empty, DefKind::AnonConst, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 218fa9740229d..f04d0e7bece4b 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -377,17 +377,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut generic_args = ThinVec::new(); for (idx, arg) in args.into_iter().enumerate() { if legacy_args_idx.contains(&idx) { - let parent_def_id = self.current_hir_id_owner; + let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.create_def( - parent_def_id.def_id, - node_id, - kw::Empty, - DefKind::AnonConst, - f.span, - ); + self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); let anon_const = AnonConst { id: node_id, value: arg }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 24748d2d00968..8315ba6fd84f8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -120,6 +120,18 @@ struct LoweringContext<'a, 'hir> { is_in_dyn_type: bool, current_hir_id_owner: hir::OwnerId, + /// Why do we need this in addition to [`Self::current_hir_id_owner`]? + /// + /// Currently (as of June 2024), anonymous constants are not HIR owners; however, + /// they do get their own DefIds. Some of these DefIds have to be created during + /// AST lowering, rather than def collection, because we can't tell until after + /// name resolution whether an anonymous constant will end up instead being a + /// [`rustc_hir::ConstArgKind::Path`]. However, to compute which generics are + /// available to an anonymous constant nested inside another, we need to make + /// sure that the parent is recorded as the parent anon const, not the enclosing + /// item. So we need to track parent defs differently from HIR owners, since they + /// will be finer-grained in the case of anon consts. + current_def_id_parent: LocalDefId, item_local_id_counter: hir::ItemLocalId, trait_map: ItemLocalMap>, @@ -162,6 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { attrs: SortedMap::default(), children: Vec::default(), current_hir_id_owner: hir::CRATE_OWNER_ID, + current_def_id_parent: CRATE_DEF_ID, item_local_id_counter: hir::ItemLocalId::ZERO, node_id_to_local_id: Default::default(), trait_map: Default::default(), @@ -592,7 +605,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO); debug_assert_eq!(_old, None); - let item = f(self); + let item = self.with_def_id_parent(def_id, f); debug_assert_eq!(def_id, item.def_id().def_id); // `f` should have consumed all the elements in these vectors when constructing `item`. debug_assert!(self.impl_trait_defs.is_empty()); @@ -612,6 +625,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.children.push((def_id, hir::MaybeOwner::Owner(info))); } + fn with_def_id_parent(&mut self, parent: LocalDefId, f: impl FnOnce(&mut Self) -> T) -> T { + let current_def_id_parent = std::mem::replace(&mut self.current_def_id_parent, parent); + let result = f(self); + self.current_def_id_parent = current_def_id_parent; + result + } + /// Installs the remapping `remap` in scope while `f` is being executed. /// This causes references to the `LocalDefId` keys to be changed to /// refer to the values instead. @@ -806,7 +826,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, kind, .. } => { // Late resolution delegates to us the creation of the `LocalDefId`. let _def_id = self.create_def( - self.current_hir_id_owner.def_id, + self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent? param, kw::UnderscoreLifetime, DefKind::LifetimeParam, @@ -1152,13 +1172,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Construct an AnonConst where the expr is the "ty"'s path. - let parent_def_id = self.current_hir_id_owner; + let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); let span = self.lower_span(ty.span); // Add a definition for the in-band const def. let def_id = self.create_def( - parent_def_id.def_id, + parent_def_id, node_id, kw::Empty, DefKind::AnonConst, @@ -1429,7 +1449,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); self.create_def( - self.current_hir_id_owner.def_id, + self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent? *def_node_id, ident.name, DefKind::TyParam, @@ -1637,7 +1657,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>], ) -> hir::TyKind<'hir> { let opaque_ty_def_id = self.create_def( - self.current_hir_id_owner.def_id, + self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent? opaque_ty_node_id, kw::Empty, DefKind::OpaqueTy, From 11b144aa984b697b8053311e9db56441b7c5b842 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sun, 2 Jun 2024 23:23:28 -0700 Subject: [PATCH 02/10] hir: Create `hir::ConstArgKind` enum This will allow lowering const params to a dedicated enum variant, rather than to an `AnonConst` that is later examined during `ty` lowering. --- compiler/rustc_ast_lowering/src/lib.rs | 6 ++-- compiler/rustc_hir/src/hir.rs | 25 +++++++++++++-- compiler/rustc_hir/src/intravisit.rs | 14 +++++++- .../src/collect/resolve_bound_vars.rs | 2 +- .../src/hir_ty_lowering/generics.rs | 5 +-- .../src/hir_ty_lowering/mod.rs | 12 ++++--- compiler/rustc_hir_pretty/src/lib.rs | 10 ++++-- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 32 ++++++++++++------- .../rustc_hir_typeck/src/method/confirm.rs | 2 +- compiler/rustc_lint/src/pass_by_value.rs | 2 +- compiler/rustc_passes/src/hir_stats.rs | 2 +- src/librustdoc/clean/mod.rs | 8 +++-- .../clippy/clippy_utils/src/hir_utils.rs | 22 ++++++++++--- 13 files changed, 102 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8315ba6fd84f8..e165b9874e1ae 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -53,7 +53,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::{self as hir}; +use rustc_hir::{self as hir, ConstArgKind}; use rustc_hir::{ ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate, }; @@ -1203,7 +1203,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) }); return GenericArg::Const(ConstArg { - value: ct, + kind: ConstArgKind::Anon(ct), is_desugared_from_effects: false, }); } @@ -1214,7 +1214,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericArg::Type(self.lower_ty(ty, itctx)) } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { - value: self.lower_anon_const(ct), + kind: ConstArgKind::Anon(self.lower_anon_const(ct)), is_desugared_from_effects: false, }), } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 3bd7b300758c4..08abcf6e214cf 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -230,11 +230,30 @@ impl<'hir> PathSegment<'hir> { #[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct ConstArg<'hir> { - pub value: &'hir AnonConst, + pub kind: ConstArgKind<'hir>, /// Indicates whether this comes from a `~const` desugaring. pub is_desugared_from_effects: bool, } +impl<'hir> ConstArg<'hir> { + pub fn span(&self) -> Span { + match self.kind { + ConstArgKind::Anon(anon) => anon.span, + } + } + + pub fn hir_id(&self) -> HirId { + match self.kind { + ConstArgKind::Anon(anon) => anon.hir_id, + } + } +} + +#[derive(Clone, Copy, Debug, HashStable_Generic)] +pub enum ConstArgKind<'hir> { + Anon(&'hir AnonConst), +} + #[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct InferArg { pub hir_id: HirId, @@ -260,7 +279,7 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(l) => l.ident.span, GenericArg::Type(t) => t.span, - GenericArg::Const(c) => c.value.span, + GenericArg::Const(c) => c.span(), GenericArg::Infer(i) => i.span, } } @@ -269,7 +288,7 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(l) => l.hir_id, GenericArg::Type(t) => t.hir_id, - GenericArg::Const(c) => c.value.hir_id, + GenericArg::Const(c) => c.hir_id(), GenericArg::Infer(i) => i.hir_id, } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 9bb3245ae05af..19582459b0eb5 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -347,6 +347,9 @@ pub trait Visitor<'v>: Sized { fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result { walk_inline_const(self, c) } + fn visit_const_arg(&mut self, c: &'v ConstArg<'v>) -> Self::Result { + walk_const_arg(self, c) + } fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result { walk_expr(self, ex) } @@ -725,6 +728,15 @@ pub fn walk_inline_const<'v, V: Visitor<'v>>( visitor.visit_nested_body(constant.body) } +pub fn walk_const_arg<'v, V: Visitor<'v>>( + visitor: &mut V, + const_arg: &'v ConstArg<'v>, +) -> V::Result { + match const_arg.kind { + ConstArgKind::Anon(anon) => visitor.visit_anon_const(anon), + } +} + pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result { try_visit!(visitor.visit_id(expression.hir_id)); match expression.kind { @@ -1216,7 +1228,7 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>( match generic_arg { GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt), GenericArg::Type(ty) => visitor.visit_ty(ty), - GenericArg::Const(ct) => visitor.visit_anon_const(&ct.value), + GenericArg::Const(ct) => visitor.visit_const_arg(ct), GenericArg::Infer(inf) => visitor.visit_infer(inf), } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index cad7870a0a1d8..43aa54254b5c3 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1594,7 +1594,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { i += 1; } GenericArg::Const(ct) => { - self.visit_anon_const(&ct.value); + self.visit_const_arg(ct); i += 1; } GenericArg::Infer(inf) => { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index b1c77db9f3700..f8b5c86092b9f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -8,10 +8,10 @@ use rustc_ast::ast::ParamKindOrd; use rustc_errors::{ codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, }; -use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; +use rustc_hir::{self as hir, ConstArgKind}; use rustc_middle::ty::{ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, }; @@ -113,7 +113,8 @@ fn generic_arg_mismatch_err( } } (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => { - let body = tcx.hir().body(cnst.value.body); + let ConstArgKind::Anon(anon) = cnst.kind; + let body = tcx.hir().body(anon.body); if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind { if let Res::Def(DefKind::Fn { .. }, id) = path.res { 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 a665306f2c6a8..0d2d83bc43f53 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -470,11 +470,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => { handle_ty_args(has_default, &inf.to_ty()) } - (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - let did = ct.value.def_id; - tcx.feed_anon_const_type(did, tcx.type_of(param.def_id)); - ty::Const::from_anon_const(tcx, did).into() - } + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => match &ct.kind { + hir::ConstArgKind::Anon(anon) => { + let did = anon.def_id; + tcx.feed_anon_const_type(did, tcx.type_of(param.def_id)); + ty::Const::from_anon_const(tcx, did).into() + } + }, (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => { self.lowerer.ct_infer(Some(param), inf.span).into() } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 5105d60ae188c..f210736a12500 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -10,7 +10,7 @@ use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; use rustc_ast_pretty::pprust::{Comments, PrintState}; -use rustc_hir as hir; +use rustc_hir::{self as hir, ConstArgKind}; use rustc_hir::{ BindingMode, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TraitBoundModifier, @@ -991,6 +991,12 @@ impl<'a> State<'a> { self.ann.nested(self, Nested::Body(constant.body)) } + fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) { + match &const_arg.kind { + ConstArgKind::Anon(anon) => self.print_anon_const(anon), + } + } + fn print_call_post(&mut self, args: &[hir::Expr<'_>]) { self.popen(); self.commasep_exprs(Inconsistent, args); @@ -1679,7 +1685,7 @@ impl<'a> State<'a> { GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt), GenericArg::Lifetime(_) => {} GenericArg::Type(ty) => s.print_type(ty), - GenericArg::Const(ct) => s.print_anon_const(&ct.value), + GenericArg::Const(ct) => s.print_const_arg(ct), GenericArg::Infer(_inf) => s.word("_"), } }); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 6da3f1dd11412..594d05e602d73 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -5,10 +5,10 @@ use crate::rvalue_scopes; use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey}; -use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; +use rustc_hir::{self as hir, ConstArg, ConstArgKind}; use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath}; use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend; use rustc_hir_analysis::hir_ty_lowering::generics::{ @@ -466,16 +466,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn lower_const_arg(&self, hir_ct: &hir::AnonConst, param_def_id: DefId) -> ty::Const<'tcx> { - let did = hir_ct.def_id; - self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id)); - let ct = ty::Const::from_anon_const(self.tcx, did); - self.register_wf_obligation( - ct.into(), - self.tcx.hir().span(hir_ct.hir_id), - ObligationCauseCode::WellFormed(None), - ); - ct + pub fn lower_const_arg( + &self, + const_arg: &ConstArg<'tcx>, + param_def_id: DefId, + ) -> ty::Const<'tcx> { + match &const_arg.kind { + ConstArgKind::Anon(anon) => { + let did = anon.def_id; + self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id)); + let ct = ty::Const::from_anon_const(self.tcx, did); + self.register_wf_obligation( + ct.into(), + self.tcx.hir().span(anon.hir_id), + ObligationCauseCode::WellFormed(None), + ); + ct + } + } } // If the type given by the user has free regions, save it for later, since @@ -1298,7 +1306,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.fcx.lower_ty(ty).raw.into() } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - self.fcx.lower_const_arg(&ct.value, param.def_id).into() + self.fcx.lower_const_arg(ct, param.def_id).into() } (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { self.fcx.ty_infer(Some(param), inf.span).into() diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index e574fde14fb0a..e70431a68ff16 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -400,7 +400,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.cfcx.lower_ty(ty).raw.into() } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - self.cfcx.lower_const_arg(&ct.value, param.def_id).into() + self.cfcx.lower_const_arg(ct, param.def_id).into() } (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { self.cfcx.ty_infer(Some(param), inf.span).into() diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index c1f5cd45dc824..fa23f120468a4 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -78,7 +78,7 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String { .tcx .sess .source_map() - .span_to_snippet(c.value.span) + .span_to_snippet(c.span()) .unwrap_or_else(|_| "_".into()), GenericArg::Infer(_) => String::from("_"), }) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 0720efebf9721..fb7529d93ed91 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -452,7 +452,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { match ga { hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt), hir::GenericArg::Type(ty) => self.visit_ty(ty), - hir::GenericArg::Const(ct) => self.visit_anon_const(&ct.value), + hir::GenericArg::Const(ct) => self.visit_const_arg(ct), hir::GenericArg::Infer(inf) => self.visit_infer(inf), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a0e28d2f55c70..ced43655b15f6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -36,10 +36,10 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry}; use rustc_errors::{codes::*, struct_span_code_err, FatalError}; -use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::PredicateOrigin; +use rustc_hir::{self as hir, ConstArgKind}; use rustc_hir_analysis::lower_ty; use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; @@ -285,10 +285,12 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> } pub(crate) fn clean_const<'tcx>( - constant: &hir::ConstArg<'_>, + constant: &hir::ConstArg<'tcx>, _cx: &mut DocContext<'tcx>, ) -> Constant { - Constant { kind: ConstantKind::Anonymous { body: constant.value.body } } + match &constant.kind { + ConstArgKind::Anon(anon) => Constant { kind: ConstantKind::Anonymous { body: anon.body } }, + } } pub(crate) fn clean_middle_const<'tcx>( diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 8706cec5d388a..437f563cabd9a 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHasher; use rustc_hir::def::Res; use rustc_hir::MatchSource::TryDesugar; use rustc_hir::{ - ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, - GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, - PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, + ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, + ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, + LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, }; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::LateContext; @@ -411,7 +411,7 @@ impl HirEqInterExpr<'_, '_, '_> { fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool { match (left, right) { - (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body), + (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l, r), (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt), (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty), (GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()), @@ -419,6 +419,12 @@ impl HirEqInterExpr<'_, '_, '_> { } } + fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool { + match (&left.kind, &right.kind) { + (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body), + } + } + fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool { left.res == right.res } @@ -1134,12 +1140,18 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.maybe_typeck_results = old_maybe_typeck_results; } + fn hash_const_arg(&mut self, const_arg: &ConstArg<'_>) { + match &const_arg.kind { + ConstArgKind::Anon(anon) => self.hash_body(anon.body), + } + } + fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) { for arg in arg_list { match *arg { GenericArg::Lifetime(l) => self.hash_lifetime(l), GenericArg::Type(ty) => self.hash_ty(ty), - GenericArg::Const(ref ca) => self.hash_body(ca.value.body), + GenericArg::Const(ref ca) => self.hash_const_arg(ca), GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()), } } From 7d7be2f0f63fffaae1fbe9ef29c52a7c47cd482c Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 16 Jul 2024 11:29:31 -0700 Subject: [PATCH 03/10] Setup ast_lowering functions for `ConstArg` --- compiler/rustc_ast_lowering/src/asm.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 114 +++++++++++++----------- compiler/rustc_hir/src/hir.rs | 4 +- 4 files changed, 69 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 4d4a6fa8a6004..269e045cf26bb 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -187,7 +187,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .emit(); } hir::InlineAsmOperand::Const { - anon_const: self.lower_anon_const(anon_const), + anon_const: self.lower_anon_const_to_anon_const(anon_const), } } InlineAsmOperand::Sym { sym } => { @@ -233,7 +233,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let anon_const = AnonConst { id: node_id, value: P(expr) }; hir::InlineAsmOperand::SymFn { - anon_const: self.lower_anon_const(&anon_const), + anon_const: self.lower_anon_const_to_anon_const(&anon_const), } } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 0ad23b5356690..311fcac82c2d2 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -713,7 +713,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id, def_id: self.local_def_id(v.id), data: self.lower_variant_data(hir_id, &v.data), - disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)), + disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)), ident: self.lower_ident(v.ident), span: self.lower_span(v.span), } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e165b9874e1ae..cdb16ef356dee 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -53,10 +53,8 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::{self as hir, ConstArgKind}; -use rustc_hir::{ - ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate, -}; +use rustc_hir::{self as hir}; +use rustc_hir::{GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate}; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; use rustc_middle::span_bug; @@ -1064,7 +1062,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { AssocItemConstraintKind::Equality { term } => { let term = match term { Term::Ty(ty) => self.lower_ty(ty, itctx).into(), - Term::Const(c) => self.lower_anon_const(c).into(), + Term::Const(c) => self.lower_anon_const_to_anon_const(c).into(), }; hir::AssocItemConstraintKind::Equality { term } } @@ -1170,42 +1168,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ty, ); - // Construct an AnonConst where the expr is the "ty"'s path. - - let parent_def_id = self.current_def_id_parent; - let node_id = self.next_node_id(); - let span = self.lower_span(ty.span); - - // Add a definition for the in-band const def. - let def_id = self.create_def( - parent_def_id, - node_id, - kw::Empty, - DefKind::AnonConst, - span, - ); - - let path_expr = Expr { - id: ty.id, - kind: ExprKind::Path(None, path.clone()), - span, - attrs: AttrVec::new(), - tokens: None, - }; - - let ct = self.with_new_scopes(span, |this| { - self.arena.alloc(hir::AnonConst { - def_id, - hir_id: this.lower_node_id(node_id), - body: this - .lower_const_body(path_expr.span, Some(&path_expr)), - span, - }) - }); - return GenericArg::Const(ConstArg { - kind: ConstArgKind::Anon(ct), - is_desugared_from_effects: false, - }); + let ct = + self.lower_const_path_to_const_arg(path, res, ty.id, ty.span); + return GenericArg::Const(ct); } } } @@ -1213,10 +1178,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } GenericArg::Type(self.lower_ty(ty, itctx)) } - ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { - kind: ConstArgKind::Anon(self.lower_anon_const(ct)), - is_desugared_from_effects: false, - }), + ast::GenericArg::Const(ct) => GenericArg::Const(self.lower_anon_const_to_const_arg(ct)), } } @@ -1375,7 +1337,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::Array(ty, length) => { hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) } - TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)), + TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)), TyKind::TraitObject(bounds, kind) => { let mut lifetime_bound = None; let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { @@ -2242,7 +2204,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { false } }) - .map(|def| self.lower_anon_const(def)); + .map(|def| self.lower_anon_const_to_anon_const(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), @@ -2380,14 +2342,66 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { "using `_` for array lengths is unstable", ) .stash(c.value.span, StashKey::UnderscoreForArrayLengths); - hir::ArrayLen::Body(self.lower_anon_const(c)) + hir::ArrayLen::Body(self.lower_anon_const_to_anon_const(c)) } } - _ => hir::ArrayLen::Body(self.lower_anon_const(c)), + _ => hir::ArrayLen::Body(self.lower_anon_const_to_anon_const(c)), + } + } + + fn lower_const_path_to_const_arg( + &mut self, + path: &Path, + _res: Res, + ty_id: NodeId, + span: Span, + ) -> &'hir hir::ConstArg<'hir> { + // Construct an AnonConst where the expr is the "ty"'s path. + + let parent_def_id = self.current_def_id_parent; + let node_id = self.next_node_id(); + let span = self.lower_span(span); + + // Add a definition for the in-band const def. + let def_id = self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span); + + let path_expr = Expr { + id: ty_id, + kind: ExprKind::Path(None, path.clone()), + span, + attrs: AttrVec::new(), + tokens: None, + }; + + let ct = self.with_new_scopes(span, |this| { + self.arena.alloc(hir::AnonConst { + def_id, + hir_id: this.lower_node_id(node_id), + body: this.lower_const_body(path_expr.span, Some(&path_expr)), + span, + }) + }); + + self.arena.alloc(hir::ConstArg { + kind: hir::ConstArgKind::Anon(ct), + is_desugared_from_effects: false, + }) + } + + fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> { + self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon)) + } + + #[instrument(level = "debug", skip(self))] + fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> { + let lowered_anon = self.lower_anon_const_to_anon_const(anon); + hir::ConstArg { + kind: hir::ConstArgKind::Anon(lowered_anon), + is_desugared_from_effects: false, } } - fn lower_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { + fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { self.arena.alloc(self.with_new_scopes(c.value.span, |this| hir::AnonConst { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 08abcf6e214cf..8a9f5b10b79b1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -270,7 +270,7 @@ impl InferArg { pub enum GenericArg<'hir> { Lifetime(&'hir Lifetime), Type(&'hir Ty<'hir>), - Const(ConstArg<'hir>), + Const(&'hir ConstArg<'hir>), Infer(InferArg), } @@ -3985,7 +3985,7 @@ mod size_asserts { static_assert_size!(FnDecl<'_>, 40); static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItemKind<'_>, 40); - static_assert_size!(GenericArg<'_>, 24); + static_assert_size!(GenericArg<'_>, 16); static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); From e7c85cb1e0c80fdd19e04ae60abc419c7a245705 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 16 Jul 2024 11:54:43 -0700 Subject: [PATCH 04/10] Setup ty::Const functions for `ConstArg` --- .../src/hir_ty_lowering/mod.rs | 11 +- compiler/rustc_middle/src/ty/consts.rs | 117 ++++++++++++------ compiler/rustc_middle/src/ty/mod.rs | 2 +- 3 files changed, 86 insertions(+), 44 deletions(-) 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 0d2d83bc43f53..62d12756832fc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -470,13 +470,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => { handle_ty_args(has_default, &inf.to_ty()) } - (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => match &ct.kind { - hir::ConstArgKind::Anon(anon) => { - let did = anon.def_id; - tcx.feed_anon_const_type(did, tcx.type_of(param.def_id)); - ty::Const::from_anon_const(tcx, did).into() - } - }, + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { + ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id)) + .into() + } (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => { self.lowerer.ct_infer(Some(param), inf.span).into() } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 32d01d07c17e7..6eae30dc3e43f 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -3,9 +3,9 @@ use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar}; use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; -use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::{self as hir, HirId}; use rustc_macros::HashStable; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; use tracing::{debug, instrument}; @@ -182,16 +182,52 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { } } +/// In some cases, [`hir::ConstArg`]s that are being used in the type system +/// through const generics need to have their type "fed" to them +/// using the query system. +/// +/// Use this enum with [`Const::from_const_arg`] to instruct it with the +/// desired behavior. +#[derive(Debug, Clone, Copy)] +pub enum FeedConstTy { + /// Feed the type. + /// + /// The `DefId` belongs to the const param that we are supplying + /// this (anon) const arg to. + Param(DefId), + /// Don't feed the type. + No, +} + impl<'tcx> Const<'tcx> { + /// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self). + #[instrument(skip(tcx), level = "debug")] + #[allow(irrefutable_let_patterns)] + pub fn from_const_arg( + tcx: TyCtxt<'tcx>, + const_arg: &'tcx hir::ConstArg<'tcx>, + feed: FeedConstTy, + ) -> Self { + if let FeedConstTy::Param(param_def_id) = feed + && let hir::ConstArgKind::Anon(anon) = &const_arg.kind + { + tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id)); + } + + match const_arg.kind { + hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id), + } + } + /// Literals and const generic parameters are eagerly converted to a constant, everything else /// becomes `Unevaluated`. #[instrument(skip(tcx), level = "debug")] pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self { let body_id = match tcx.hir_node_by_def_id(def) { hir::Node::AnonConst(ac) => ac.body, - _ => span_bug!( + node => span_bug!( tcx.def_span(def.to_def_id()), - "from_anon_const can only process anonymous constants" + "from_anon_const can only process anonymous constants, not {node:?}" ), }; @@ -200,7 +236,7 @@ impl<'tcx> Const<'tcx> { let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); - match Self::try_from_lit_or_param(tcx, ty, expr) { + match Self::try_from_lit(tcx, ty, expr) { Some(v) => v, None => ty::Const::new_unevaluated( tcx, @@ -212,12 +248,36 @@ impl<'tcx> Const<'tcx> { } } + /// Lower a const param to a [`Const`]. + /// + /// IMPORTANT: `qpath` must be a const param, otherwise this will panic + fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self { + let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) = + qpath + else { + span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param") + }; + + match tcx.named_bound_var(hir_id) { + Some(rbv::ResolvedArg::EarlyBound(_)) => { + // Find the name and index of the const parameter by indexing the generics of + // the parent item and construct a `ParamConst`. + let item_def_id = tcx.parent(def_id); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&def_id]; + let name = tcx.item_name(def_id); + ty::Const::new_param(tcx, ty::ParamConst::new(index, name)) + } + Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { + ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)) + } + Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar), + arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id), + } + } + #[instrument(skip(tcx), level = "debug")] - fn try_from_lit_or_param( - tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, - expr: &'tcx hir::Expr<'tcx>, - ) -> Option { + fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option { // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments // currently have to be wrapped in curly brackets, so it's necessary to special-case. let expr = match &expr.kind { @@ -250,34 +310,19 @@ impl<'tcx> Const<'tcx> { } } - // FIXME(const_generics): We currently have to special case parameters because `min_const_generics` - // does not provide the parents generics to anonymous constants. We still allow generic const - // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to - // ever try to instantiate the generic parameters in their bodies. - match expr.kind { - hir::ExprKind::Path(hir::QPath::Resolved( + if let hir::ExprKind::Path( + qpath @ hir::QPath::Resolved( _, - &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }, - )) => { - match tcx.named_bound_var(expr.hir_id) { - Some(rbv::ResolvedArg::EarlyBound(_)) => { - // Find the name and index of the const parameter by indexing the generics of - // the parent item and construct a `ParamConst`. - let item_def_id = tcx.parent(def_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; - let name = tcx.item_name(def_id); - Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name))) - } - Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { - Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))) - } - Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)), - arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id), - } - } - _ => None, + &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, + ), + ) = expr.kind + { + // FIXME: once ConstArgKind::Path added, uncomment span_bug and delete return + // span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible") + return Some(Self::from_param(tcx, qpath, expr.hir_id)); } + + None } #[inline] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9a4562e9cfc83..bd073cd891f69 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -86,7 +86,7 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, + Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, From 8818708a317e28a2fa578d0b71640cd9865000e6 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 4 Jun 2024 17:21:54 -0700 Subject: [PATCH 05/10] Use `ConstArg` for assoc item constraints --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_hir/src/hir.rs | 12 +++++----- compiler/rustc_hir/src/intravisit.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- .../src/hir_ty_lowering/bounds.rs | 23 +++++++++++++------ .../src/hir_ty_lowering/errors.rs | 5 ++-- .../src/hir_ty_lowering/mod.rs | 3 ++- compiler/rustc_hir_pretty/src/lib.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- 9 files changed, 31 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index cdb16ef356dee..3ff220b8a2945 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1062,7 +1062,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { AssocItemConstraintKind::Equality { term } => { let term = match term { Term::Ty(ty) => self.lower_ty(ty, itctx).into(), - Term::Const(c) => self.lower_anon_const_to_anon_const(c).into(), + Term::Const(c) => self.lower_anon_const_to_const_arg(c).into(), }; hir::AssocItemConstraintKind::Equality { term } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 8a9f5b10b79b1..f74a15935187d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -242,7 +242,7 @@ impl<'hir> ConstArg<'hir> { } } - pub fn hir_id(&self) -> HirId { + pub fn anon_const_hir_id(&self) -> HirId { match self.kind { ConstArgKind::Anon(anon) => anon.hir_id, } @@ -288,7 +288,7 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(l) => l.hir_id, GenericArg::Type(t) => t.hir_id, - GenericArg::Const(c) => c.hir_id(), + GenericArg::Const(c) => c.anon_const_hir_id(), // FIXME GenericArg::Infer(i) => i.hir_id, } } @@ -2453,7 +2453,7 @@ impl<'hir> AssocItemConstraint<'hir> { } /// Obtain the const on the RHS of an assoc const equality constraint if applicable. - pub fn ct(self) -> Option<&'hir AnonConst> { + pub fn ct(self) -> Option<&'hir ConstArg<'hir>> { match self.kind { AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct), _ => None, @@ -2464,7 +2464,7 @@ impl<'hir> AssocItemConstraint<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum Term<'hir> { Ty(&'hir Ty<'hir>), - Const(&'hir AnonConst), + Const(&'hir ConstArg<'hir>), } impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> { @@ -2473,8 +2473,8 @@ impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> { } } -impl<'hir> From<&'hir AnonConst> for Term<'hir> { - fn from(c: &'hir AnonConst) -> Self { +impl<'hir> From<&'hir ConstArg<'hir>> for Term<'hir> { + fn from(c: &'hir ConstArg<'hir>) -> Self { Term::Const(c) } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 19582459b0eb5..ea67bfdb86c94 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1290,7 +1290,7 @@ pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>( match constraint.kind { AssocItemConstraintKind::Equality { ref term } => match term { Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)), - Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)), + Term::Const(ref c) => try_visit!(visitor.visit_const_arg(c)), }, AssocItemConstraintKind::Bound { bounds } => { walk_list!(visitor, visit_param_bound, bounds) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 974dd415f464c..d628ed955c657 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -224,7 +224,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .iter() .copied() .filter_map(AssocItemConstraint::ct) - .position(|ct| ct.hir_id == hir_id) + .position(|ct| ct.anon_const_hir_id() == hir_id) .map(|idx| (idx, seg)) }) }) else { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index a1feef9e15b7e..1e89d7201d0c4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -413,12 +413,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); // Provide the resolved type of the associated constant to `type_of(AnonConst)`. - if let Some(anon_const) = constraint.ct() { - let ty = alias_term - .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args)); - let ty = - check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id); - tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty)); + if let Some(const_arg) = constraint.ct() { + #[allow(irrefutable_let_patterns)] // FIXME + if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind { + let ty = alias_term + .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args)); + let ty = check_assoc_const_binding_type( + self, + constraint.ident, + ty, + constraint.hir_id, + ); + tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty)); + } } alias_term @@ -435,7 +442,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::AssocItemConstraintKind::Equality { term } => { let term = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), - hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(), + hir::Term::Const(ct) => { + ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into() + } }; // Find any late-bound regions declared in `ty` that are not diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 5e595488ea7a8..706afdb9d3a16 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -340,7 +340,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { { let span = match term { hir::Term::Ty(ty) => ty.span, - hir::Term::Const(ct) => tcx.def_span(ct.def_id), + hir::Term::Const(ct) => ct.span(), }; (span, Some(ident.span), assoc_item.kind, assoc_kind) } else { @@ -1296,8 +1296,7 @@ pub fn prohibit_assoc_item_constraint( hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) }, GenericParamDefKind::Const { .. }, ) => { - let span = tcx.hir().span(c.hir_id); - suggest_direct_use(&mut err, span); + suggest_direct_use(&mut err, c.span()); } (hir::AssocItemConstraintKind::Bound { bounds }, _) => { // Suggest `impl Trait for Foo` when finding 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 62d12756832fc..26f9820b8720b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -911,7 +911,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let term: ty::Term<'_> = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Const(ct) => { - ty::Const::from_anon_const(tcx, ct.def_id).into() + ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No) + .into() } }; // FIXME(#97583): This isn't syntactically well-formed! diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index f210736a12500..8ebd9cb16670f 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1726,7 +1726,7 @@ impl<'a> State<'a> { self.word_space("="); match term { Term::Ty(ty) => self.print_type(ty), - Term::Const(ref c) => self.print_anon_const(c), + Term::Const(ref c) => self.print_const_arg(c), } } hir::AssocItemConstraintKind::Bound { bounds } => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ced43655b15f6..6849a63101010 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -433,7 +433,7 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te match term { hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)), hir::Term::Const(c) => Term::Constant(clean_middle_const( - ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, c.def_id)), + ty::Binder::dummy(ty::Const::from_const_arg(cx.tcx, c, ty::FeedConstTy::No)), cx, )), } From 67fccb70455903d05a977d83954a0f91e6f4d6e2 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 4 Jun 2024 18:24:08 -0700 Subject: [PATCH 06/10] Use `ConstArg` for array lengths --- compiler/rustc_ast_lowering/src/lib.rs | 4 +-- compiler/rustc_hir/src/hir.rs | 14 +++++---- compiler/rustc_hir/src/intravisit.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 4 +-- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 6 ++-- .../src/error_reporting/infer/mod.rs | 4 +-- src/librustdoc/clean/mod.rs | 18 +++++++++--- .../clippy_lints/src/large_stack_arrays.rs | 9 +++--- .../clippy_lints/src/trailing_empty_array.rs | 6 ++-- .../clippy/clippy_lints/src/utils/author.rs | 29 ++++++++++++++----- .../clippy/clippy_utils/src/hir_utils.rs | 4 +-- src/tools/clippy/clippy_utils/src/lib.rs | 18 +++++++----- 14 files changed, 77 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3ff220b8a2945..fd55cbf64f2ac 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2342,10 +2342,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { "using `_` for array lengths is unstable", ) .stash(c.value.span, StashKey::UnderscoreForArrayLengths); - hir::ArrayLen::Body(self.lower_anon_const_to_anon_const(c)) + hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)) } } - _ => hir::ArrayLen::Body(self.lower_anon_const_to_anon_const(c)), + _ => hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)), } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f74a15935187d..f996b225290f3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -242,6 +242,11 @@ impl<'hir> ConstArg<'hir> { } } + // FIXME: convert to field, where ConstArg has its own HirId + pub fn hir_id(&self) -> HirId { + self.anon_const_hir_id() + } + pub fn anon_const_hir_id(&self) -> HirId { match self.kind { ConstArgKind::Anon(anon) => anon.hir_id, @@ -288,7 +293,7 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(l) => l.hir_id, GenericArg::Type(t) => t.hir_id, - GenericArg::Const(c) => c.anon_const_hir_id(), // FIXME + GenericArg::Const(c) => c.hir_id(), GenericArg::Infer(i) => i.hir_id, } } @@ -1617,15 +1622,14 @@ pub type Lit = Spanned; #[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum ArrayLen<'hir> { Infer(InferArg), - Body(&'hir AnonConst), + Body(&'hir ConstArg<'hir>), } impl ArrayLen<'_> { pub fn hir_id(&self) -> HirId { match self { - ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(AnonConst { hir_id, .. }) => { - *hir_id - } + ArrayLen::Infer(InferArg { hir_id, .. }) => *hir_id, + ArrayLen::Body(ct) => ct.hir_id(), } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index ea67bfdb86c94..848d2ca99cb49 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -711,7 +711,7 @@ pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen<'v> match len { // FIXME: Use `visit_infer` here. ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), - ArrayLen::Body(c) => visitor.visit_anon_const(c), + ArrayLen::Body(c) => visitor.visit_const_arg(c), } } 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 26f9820b8720b..8dadfbeee6cb6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2140,7 +2140,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let length = match length { hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), hir::ArrayLen::Body(constant) => { - ty::Const::from_anon_const(tcx, constant.def_id) + ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No) } }; diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 8ebd9cb16670f..eeb711f9e893d 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -983,7 +983,7 @@ impl<'a> State<'a> { fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) { match len { hir::ArrayLen::Infer(..) => self.word("_"), - hir::ArrayLen::Body(ct) => self.print_anon_const(ct), + hir::ArrayLen::Body(ct) => self.print_const_arg(ct), } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 035a3429ed76e..e957330d9a1c5 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1439,9 +1439,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; }; if let hir::TyKind::Array(_, length) = ty.peel_refs().kind - && let hir::ArrayLen::Body(&hir::AnonConst { hir_id, .. }) = length + && let hir::ArrayLen::Body(ct) = length { - let span = self.tcx.hir().span(hir_id); + let span = ct.span(); self.dcx().try_steal_modify_and_emit_err( span, StashKey::UnderscoreForArrayLengths, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 594d05e602d73..057168c00ac7c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -457,9 +457,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { match length { hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), - hir::ArrayLen::Body(anon_const) => { - let span = self.tcx.def_span(anon_const.def_id); - let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id); + hir::ArrayLen::Body(const_arg) => { + let span = const_arg.span(); + let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No); self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None)); self.normalize(span, c) } diff --git a/compiler/rustc_infer/src/error_reporting/infer/mod.rs b/compiler/rustc_infer/src/error_reporting/infer/mod.rs index ddd5818203cfd..e8b37604f6b15 100644 --- a/compiler/rustc_infer/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_infer/src/error_reporting/infer/mod.rs @@ -1762,9 +1762,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; if let Some(tykind) = tykind && let hir::TyKind::Array(_, length) = tykind - && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length + && let hir::ArrayLen::Body(ct) = length { - let span = self.tcx.hir().span(*hir_id); + let span = ct.span(); Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found }) } else { None diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6849a63101010..7172f9d41cb01 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1822,7 +1822,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T TyKind::Array(ty, ref length) => { let length = match length { hir::ArrayLen::Infer(..) => "_".to_string(), - hir::ArrayLen::Body(anon_const) => { + hir::ArrayLen::Body(const_arg) => { // NOTE(min_const_generics): We can't use `const_eval_poly` for constants // as we currently do not supply the parent generics to anonymous constants // but do allow `ConstKind::Param`. @@ -1830,9 +1830,19 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T // `const_eval_poly` tries to first substitute generic parameters which // results in an ICE while manually constructing the constant and using `eval` // does nothing for `ConstKind::Param`. - let ct = ty::Const::from_anon_const(cx.tcx, anon_const.def_id); - let param_env = cx.tcx.param_env(anon_const.def_id); - print_const(cx, ct.normalize(cx.tcx, param_env)) + let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No); + #[allow(irrefutable_let_patterns)] // FIXME + let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) = + const_arg.kind + { + // Only anon consts can implicitly capture params. + // FIXME: is this correct behavior? + let param_env = cx.tcx.param_env(*def_id); + ct.normalize(cx.tcx, param_env) + } else { + ct + }; + print_const(cx, ct) } }; diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index c9bfc9c85d958..d94b0cce94865 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -106,13 +106,12 @@ fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool { /// /// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the /// correct result. - fn repeat_expr_might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool { - let ExprKind::Repeat(_, ArrayLen::Body(anon_const)) = expr.kind else { + fn repeat_expr_might_be_expanded<'tcx>(expr: &Expr<'tcx>) -> bool { + let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else { return false; }; - let len_span = cx.tcx.def_span(anon_const.def_id); - !expr.span.contains(len_span) + !expr.span.contains(len_ct.span()) } - expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(cx, expr) + expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(expr) } diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs index 462084e96a864..db8c63892b84e 100644 --- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::has_repr_attr; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::Const; +use rustc_middle::ty::{Const, FeedConstTy}; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -53,14 +53,14 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray { } } -fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_>) -> bool { +fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { if let ItemKind::Struct(data, _) = &item.kind // First check if last field is an array && let Some(last_field) = data.fields().last() && let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind // Then check if that array is zero-sized - && let length = Const::from_anon_const(cx.tcx, length.def_id) + && let length = Const::from_const_arg(cx.tcx, length, FeedConstTy::No) && let length = length.try_eval_target_usize(cx.tcx, cx.param_env) && let Some(length) = length { diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index e9d69407df8b5..441144d4bd11c 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -5,10 +5,9 @@ use clippy_utils::{get_attr, higher}; use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_ast::LitIntType; use rustc_data_structures::fx::FxHashMap; -use rustc_hir as hir; use rustc_hir::{ - ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatKind, - QPath, StmtKind, TyKind, + self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, + ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; @@ -270,6 +269,22 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } } + fn const_arg(&self, const_arg: &Binding<&ConstArg<'_>>) { + match const_arg.value.kind { + // FIXME: uncomment for ConstArgKind::Path + // ConstArgKind::Path(ref qpath) => { + // bind!(self, qpath); + // chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind"); + // self.qpath(qpath); + // }, + ConstArgKind::Anon(anon_const) => { + bind!(self, anon_const); + chain!(self, "let ConstArgKind::({anon_const}) = {const_arg}.kind"); + self.body(field!(anon_const.body)); + }, + } + } + fn lit(&self, lit: &Binding<&Lit>) { let kind = |kind| chain!(self, "let LitKind::{kind} = {lit}.node"); macro_rules! kind { @@ -602,10 +617,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.expr(value); match length.value { ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"), - ArrayLen::Body(anon_const) => { - bind!(self, anon_const); - chain!(self, "let ArrayLen::Body({anon_const}) = {length}"); - self.body(field!(anon_const.body)); + ArrayLen::Body(const_arg) => { + bind!(self, const_arg); + chain!(self, "let ArrayLen::Body({const_arg}) = {length}"); + self.const_arg(const_arg); }, } }, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 437f563cabd9a..ae968067850ef 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -227,7 +227,7 @@ impl HirEqInterExpr<'_, '_, '_> { pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool { match (left, right) { (ArrayLen::Infer(..), ArrayLen::Infer(..)) => true, - (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_body(l_ct.body, r_ct.body), + (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct), (_, _) => false, } } @@ -1129,7 +1129,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_array_length(&mut self, length: ArrayLen<'_>) { match length { ArrayLen::Infer(..) => {}, - ArrayLen::Body(anon_const) => self.hash_body(anon_const.body), + ArrayLen::Body(ct) => self.hash_const_arg(ct), } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index bdb3b5e45c48d..f562d9787dc7f 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -102,11 +102,11 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ - self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstContext, - Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, - ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, - PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, - TyKind, UnOp, + self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, + ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, + ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, + Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, + TraitRef, TyKind, UnOp, }; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{LateContext, Level, Lint, LintContext}; @@ -904,7 +904,9 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { }, ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)), ExprKind::Repeat(x, ArrayLen::Body(len)) => { - if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind + #[allow(irrefutable_let_patterns)] // FIXME + if let ConstArgKind::Anon(anon_const) = len.kind + && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let LitKind::Int(v, _) = const_lit.node && v <= 32 && is_default_equivalent(cx, x) @@ -933,7 +935,9 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: & }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String), ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec), ExprKind::Repeat(_, ArrayLen::Body(len)) => { - if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind + #[allow(irrefutable_let_patterns)] // FIXME + if let ConstArgKind::Anon(anon_const) = len.kind + && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let LitKind::Int(v, _) = const_lit.node { return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec); From 1c49d406b6496f9d984816f0d6814a38cd92c2de Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 7 Jun 2024 20:26:50 -0700 Subject: [PATCH 07/10] Use `ConstArg` for const param defaults Now everything that actually affects the type system (i.e., excluding const blocks, enum variant discriminants, etc.) *should* be using `ConstArg`. --- compiler/rustc_ast_lowering/src/index.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 22 +++++++++++-------- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_hir/src/intravisit.rs | 6 ++--- compiler/rustc_hir_analysis/src/collect.rs | 5 ++++- .../src/collect/predicates_of.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 8 +++---- src/librustdoc/clean/mod.rs | 5 +++-- 12 files changed, 34 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 44f37b5533a67..b98a33c4b1858 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -181,7 +181,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { intravisit::walk_generic_param(self, param); } - fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) { + fn visit_const_param_default(&mut self, param: HirId, ct: &'hir ConstArg<'hir>) { self.with_parent(param, |this| { intravisit::walk_const_param_default(this, ct); }) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 311fcac82c2d2..e20b191534427 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1601,7 +1601,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if let Some((span, hir_id, def_id)) = host_param_parts { let const_node_id = self.next_node_id(); - let anon_const = + let anon_const_did = self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span); let const_id = self.next_id(); @@ -1609,7 +1609,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bool_id = self.next_id(); self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); - self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id))); + self.children.push((anon_const_did, hir::MaybeOwner::NonOwner(const_id))); let const_body = self.lower_body(|this| { ( @@ -1624,6 +1624,16 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }); + let default_ac = self.arena.alloc(hir::AnonConst { + def_id: anon_const_did, + hir_id: const_id, + body: const_body, + span, + }); + let default_ct = self.arena.alloc(hir::ConstArg { + kind: hir::ConstArgKind::Anon(default_ac), + is_desugared_from_effects: true, + }); let param = hir::GenericParam { def_id, hir_id, @@ -1647,13 +1657,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }), )), )), - // FIXME(effects) we might not need a default. - default: Some(self.arena.alloc(hir::AnonConst { - def_id: anon_const, - hir_id: const_id, - body: const_body, - span, - })), + default: Some(default_ct), is_host_effect: true, synthetic: true, }, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index fd55cbf64f2ac..dfb27c8cfd980 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2204,7 +2204,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { false } }) - .map(|def| self.lower_anon_const_to_anon_const(def)); + .map(|def| self.lower_anon_const_to_const_arg(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f996b225290f3..27218d687e1e7 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -548,7 +548,7 @@ pub enum GenericParamKind<'hir> { Const { ty: &'hir Ty<'hir>, /// Optional default value for the const generic param - default: Option<&'hir AnonConst>, + default: Option<&'hir ConstArg<'hir>>, is_host_effect: bool, synthetic: bool, }, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 848d2ca99cb49..db8c704cd2f25 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -367,7 +367,7 @@ pub trait Visitor<'v>: Sized { fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result { walk_generic_param(self, p) } - fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) -> Self::Result { + fn visit_const_param_default(&mut self, _param: HirId, ct: &'v ConstArg<'v>) -> Self::Result { walk_const_param_default(self, ct) } fn visit_generics(&mut self, g: &'v Generics<'v>) -> Self::Result { @@ -940,9 +940,9 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>( pub fn walk_const_param_default<'v, V: Visitor<'v>>( visitor: &mut V, - ct: &'v AnonConst, + ct: &'v ConstArg<'v>, ) -> V::Result { - visitor.visit_anon_const(ct) + visitor.visit_const_arg(ct) } pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e0aad29916323..13aa15cdabdc5 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -304,7 +304,10 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { self.tcx.ensure().type_of(param.def_id); if let Some(default) = default { // need to store default and type of default - self.tcx.ensure().type_of(default.def_id); + #[allow(irrefutable_let_patterns)] // FIXME + if let hir::ConstArgKind::Anon(ac) = default.kind { + self.tcx.ensure().type_of(ac.def_id); + } self.tcx.ensure().const_param_default(param.def_id); } } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index b89d034fc2e3f..9e430c83e20d7 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -388,7 +388,7 @@ fn const_evaluatable_predicates_of( } } - fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) { + fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) { // Do not look into const param defaults, // these get checked when they are actually instantiated. // diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 43aa54254b5c3..7930f54038daf 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -954,7 +954,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { GenericParamKind::Const { ty, default, .. } => { self.visit_ty(ty); if let Some(default) = default { - self.visit_body(self.tcx.hir().body(default.body)); + self.visit_const_arg(default); } } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index d628ed955c657..10c44fb04ae9d 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -73,7 +73,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { def_id: param_def_id, kind: GenericParamKind::Const { default: Some(ct), .. }, .. - }) if ct.hir_id == hir_id => { + }) if ct.anon_const_hir_id() == hir_id => { return tcx .type_of(param_def_id) .no_bound_vars() diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index eeb711f9e893d..95bf07c907b81 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2161,7 +2161,7 @@ impl<'a> State<'a> { if let Some(default) = default { self.space(); self.word_space("="); - self.print_anon_const(default); + self.print_const_arg(default); } } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 6eae30dc3e43f..a5c4d8b379221 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -505,15 +505,15 @@ pub fn const_param_default<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, ) -> ty::EarlyBinder<'tcx, Const<'tcx>> { - let default_def_id = match tcx.hir_node_by_def_id(def_id) { + let default_ct = match tcx.hir_node_by_def_id(def_id) { hir::Node::GenericParam(hir::GenericParam { - kind: hir::GenericParamKind::Const { default: Some(ac), .. }, + kind: hir::GenericParamKind::Const { default: Some(ct), .. }, .. - }) => ac.def_id, + }) => ct, _ => span_bug!( tcx.def_span(def_id), "`const_param_default` expected a generic parameter with a constant" ), }; - ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id)) + ty::EarlyBinder::bind(Const::from_const_arg(tcx, default_ct, FeedConstTy::No)) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7172f9d41cb01..a91e5233281cf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -635,8 +635,9 @@ fn clean_generic_param<'tcx>( param.name.ident().name, GenericParamDefKind::Const { ty: Box::new(clean_ty(ty, cx)), - default: default - .map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())), + default: default.map(|ct| { + Box::new(ty::Const::from_const_arg(cx.tcx, ct, ty::FeedConstTy::No).to_string()) + }), synthetic, }, ), From 37ed7a4438a24bcbe13986c82f193fd8e8d88221 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 16 Jul 2024 19:07:36 -0700 Subject: [PATCH 08/10] Add `ConstArgKind::Path` and make `ConstArg` its own HIR node This is a very large commit since a lot needs to be changed in order to make the tests pass. The salient changes are: - `ConstArgKind` gets a new `Path` variant, and all const params are now represented using it. Non-param paths still use `ConstArgKind::Anon` to prevent this change from getting too large, but they will soon use the `Path` variant too. - `ConstArg` gets a distinct `hir_id` field and its own variant in `hir::Node`. This affected many parts of the compiler that expected the parent of an `AnonConst` to be the containing context (e.g., an array repeat expression). They have been changed to check the "grandparent" where necessary. - Some `ast::AnonConst`s now have their `DefId`s created in rustc_ast_lowering rather than `DefCollector`. This is because in some cases they will end up becoming a `ConstArgKind::Path` instead, which has no `DefId`. We have to solve this in a hacky way where we guess whether the `AnonConst` could end up as a path const since we can't know for sure until after name resolution (`N` could refer to a free const or a nullary struct). If it has no chance as being a const param, then we create a `DefId` in `DefCollector` -- otherwise we decide during ast_lowering. This will have to be updated once all path consts use `ConstArgKind::Path`. - We explicitly use `ConstArgHasType` for array lengths, rather than implicitly relying on anon const type feeding -- this is due to the addition of `ConstArgKind::Path`. - Some tests have their outputs changed, but the changes are for the most part minor (including removing duplicate or almost-duplicate errors). One test now ICEs, but it is for an incomplete, unstable feature and is now tracked at #127009. --- compiler/rustc_ast_lowering/src/asm.rs | 17 +- compiler/rustc_ast_lowering/src/expr.rs | 127 ++++++++------- compiler/rustc_ast_lowering/src/index.rs | 10 ++ compiler/rustc_ast_lowering/src/item.rs | 9 +- compiler/rustc_ast_lowering/src/lib.rs | 150 ++++++++++++++---- compiler/rustc_hir/src/hir.rs | 44 +++-- compiler/rustc_hir/src/intravisit.rs | 6 +- compiler/rustc_hir_analysis/src/collect.rs | 1 - .../src/collect/generics_of.rs | 11 +- .../rustc_hir_analysis/src/collect/type_of.rs | 87 ++++++---- .../src/hir_ty_lowering/bounds.rs | 1 - .../src/hir_ty_lowering/generics.rs | 13 +- .../src/hir_ty_lowering/mod.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 + .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 25 ++- compiler/rustc_middle/src/hir/map/mod.rs | 5 +- compiler/rustc_middle/src/ty/consts.rs | 19 ++- .../rustc_middle/src/ty/typeck_results.rs | 4 +- compiler/rustc_resolve/src/def_collector.rs | 15 +- .../rustc_trait_selection/src/traits/wf.rs | 16 +- src/librustdoc/clean/mod.rs | 4 +- src/librustdoc/clean/types.rs | 12 +- .../clippy/clippy_lints/src/utils/author.rs | 13 +- .../clippy/clippy_utils/src/hir_utils.rs | 6 + src/tools/clippy/clippy_utils/src/lib.rs | 2 - .../clippy/tests/ui/author/repeat.stdout | 3 +- .../clippy/tests/ui/min_ident_chars.stderr | 8 +- tests/crashes/127009.rs | 11 ++ .../ui-fulldeps/stable-mir/check_instance.rs | 2 +- .../generic_const_type_mismatch.rs | 4 +- .../generic_const_type_mismatch.stderr | 20 +-- .../ui/const-generics/bad-subst-const-kind.rs | 2 +- .../bad-subst-const-kind.stderr | 13 +- .../generic_const_exprs/type_mismatch.rs | 2 +- .../generic_const_exprs/type_mismatch.stderr | 12 +- .../unevaluated-const-ice-119731.rs | 4 +- .../unevaluated-const-ice-119731.stderr | 4 +- .../const-generics/issues/issue-88119.stderr | 34 ++-- .../repeat_expr_hack_gives_right_generics.rs | 2 + ...peat_expr_hack_gives_right_generics.stderr | 11 +- tests/ui/const-generics/transmute-fail.rs | 5 +- tests/ui/const-generics/transmute-fail.stderr | 54 +++---- tests/ui/const-generics/type_mismatch.rs | 4 +- tests/ui/const-generics/type_mismatch.stderr | 20 +-- tests/ui/consts/issue-36163.stderr | 6 +- tests/ui/lifetimes/issue-95023.rs | 1 - tests/ui/lifetimes/issue-95023.stderr | 10 +- .../const-trait-bounds.stderr | 17 +- ...t-proj-ty-as-type-of-const-issue-125757.rs | 1 - ...oj-ty-as-type-of-const-issue-125757.stderr | 14 +- .../bad-const-wf-doesnt-specialize.rs | 1 - .../bad-const-wf-doesnt-specialize.stderr | 14 +- tests/ui/stats/hir-stats.stderr | 12 +- .../capture-late-ct-in-anon.rs | 11 -- .../capture-late-ct-in-anon.stderr | 19 --- tests/ui/transmutability/issue-101739-1.rs | 1 - .../ui/transmutability/issue-101739-1.stderr | 11 +- tests/ui/transmutability/issue-101739-2.rs | 2 +- .../ui/transmutability/issue-101739-2.stderr | 11 +- .../const-in-impl-fn-return-type.rs | 2 +- .../const-in-impl-fn-return-type.stderr | 6 +- 61 files changed, 541 insertions(+), 414 deletions(-) create mode 100644 tests/crashes/127009.rs delete mode 100644 tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs delete mode 100644 tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 269e045cf26bb..de0874af934cf 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -224,13 +224,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Wrap the expression in an AnonConst. let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); - self.create_def( - parent_def_id, - node_id, - kw::Empty, - DefKind::AnonConst, - *op_sp, - ); + // HACK(min_generic_const_args): see lower_anon_const + if !expr.is_potential_trivial_const_arg() { + self.create_def( + parent_def_id, + node_id, + kw::Empty, + DefKind::AnonConst, + *op_sp, + ); + } let anon_const = AnonConst { id: node_id, value: P(expr) }; hir::InlineAsmOperand::SymFn { anon_const: self.lower_anon_const_to_anon_const(&anon_const), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f04d0e7bece4b..d870f9fe0aef2 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -75,10 +75,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), ExprKind::ConstBlock(c) => { - let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock { - def_id: this.local_def_id(c.id), - hir_id: this.lower_node_id(c.id), - body: this.lower_const_body(c.value.span, Some(&c.value)), + let c = self.with_new_scopes(c.value.span, |this| { + let def_id = this.local_def_id(c.id); + hir::ConstBlock { + def_id, + hir_id: this.lower_node_id(c.id), + body: this.with_def_id_parent(def_id, |this| { + this.lower_const_body(c.value.span, Some(&c.value)) + }), + } }); hir::ExprKind::ConstBlock(c) } @@ -380,8 +385,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); - // Add a definition for the in-band const def. - self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); + // HACK(min_generic_const_args): see lower_anon_const + if !arg.is_potential_trivial_const_arg() { + // Add a definition for the in-band const def. + self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); + } let anon_const = AnonConst { id: node_id, value: arg }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); @@ -616,6 +624,7 @@ impl<'hir> LoweringContext<'_, 'hir> { coroutine_source: hir::CoroutineSource, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { + let closure_def_id = self.local_def_id(closure_node_id); let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source); // The `async` desugaring takes a resume argument and maintains a `task_context`, @@ -666,22 +675,24 @@ impl<'hir> LoweringContext<'_, 'hir> { lifetime_elision_allowed: false, }); - let body = self.lower_body(move |this| { - this.coroutine_kind = Some(coroutine_kind); + let body = self.with_def_id_parent(closure_def_id, move |this| { + this.lower_body(move |this| { + this.coroutine_kind = Some(coroutine_kind); - let old_ctx = this.task_context; - if task_context.is_some() { - this.task_context = task_context; - } - let res = body(this); - this.task_context = old_ctx; + let old_ctx = this.task_context; + if task_context.is_some() { + this.task_context = task_context; + } + let res = body(this); + this.task_context = old_ctx; - (params, res) + (params, res) + }) }); // `static |<_task_context?>| -> { }`: hir::ExprKind::Closure(self.arena.alloc(hir::Closure { - def_id: self.local_def_id(closure_node_id), + def_id: closure_def_id, binder: hir::ClosureBinder::Default, capture_clause, bound_generic_params: &[], @@ -960,27 +971,30 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: Span, fn_arg_span: Span, ) -> hir::ExprKind<'hir> { + let closure_def_id = self.local_def_id(closure_id); let (binder_clause, generic_params) = self.lower_closure_binder(binder); let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| { - let mut coroutine_kind = if this - .attrs - .get(&closure_hir_id.local_id) - .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine))) - { - Some(hir::CoroutineKind::Coroutine(Movability::Movable)) - } else { - None - }; - let body_id = this.lower_fn_body(decl, |this| { - this.coroutine_kind = coroutine_kind; - let e = this.lower_expr_mut(body); - coroutine_kind = this.coroutine_kind; - e - }); - let coroutine_option = - this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); - (body_id, coroutine_option) + this.with_def_id_parent(closure_def_id, move |this| { + let mut coroutine_kind = if this + .attrs + .get(&closure_hir_id.local_id) + .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine))) + { + Some(hir::CoroutineKind::Coroutine(Movability::Movable)) + } else { + None + }; + let body_id = this.lower_fn_body(decl, |this| { + this.coroutine_kind = coroutine_kind; + let e = this.lower_expr_mut(body); + coroutine_kind = this.coroutine_kind; + e + }); + let coroutine_option = + this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); + (body_id, coroutine_option) + }) }); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); @@ -988,7 +1002,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { - def_id: self.local_def_id(closure_id), + def_id: closure_def_id, binder: binder_clause, capture_clause, bound_generic_params, @@ -1060,6 +1074,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: Span, fn_arg_span: Span, ) -> hir::ExprKind<'hir> { + let closure_def_id = self.local_def_id(closure_id); let (binder_clause, generic_params) = self.lower_closure_binder(binder); assert_matches!( @@ -1069,27 +1084,29 @@ impl<'hir> LoweringContext<'_, 'hir> { ); let body = self.with_new_scopes(fn_decl_span, |this| { - let inner_decl = - FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - - // Transform `async |x: u8| -> X { ... }` into - // `|x: u8| || -> X { ... }`. - let body_id = this.lower_body(|this| { - let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( - &inner_decl, - |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), - fn_decl_span, - body.span, - coroutine_kind, - hir::CoroutineSource::Closure, - ); + this.with_def_id_parent(closure_def_id, |this| { + let inner_decl = + FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; + + // Transform `async |x: u8| -> X { ... }` into + // `|x: u8| || -> X { ... }`. + let body_id = this.lower_body(|this| { + let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( + &inner_decl, + |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), + fn_decl_span, + body.span, + coroutine_kind, + hir::CoroutineSource::Closure, + ); - let hir_id = this.lower_node_id(coroutine_kind.closure_id()); - this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); + let hir_id = this.lower_node_id(coroutine_kind.closure_id()); + this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); - (parameters, expr) - }); - body_id + (parameters, expr) + }); + body_id + }) }); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); @@ -1100,7 +1117,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { - def_id: self.local_def_id(closure_id), + def_id: closure_def_id, binder: binder_clause, capture_clause, bound_generic_params, diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index b98a33c4b1858..23729124e21a9 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -229,6 +229,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_anon_const(&mut self, constant: &'hir AnonConst) { + // FIXME: use real span? self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant)); self.with_parent(constant.hir_id, |this| { @@ -244,6 +245,15 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) { + // FIXME: use real span? + self.insert(DUMMY_SP, const_arg.hir_id, Node::ConstArg(const_arg)); + + self.with_parent(const_arg.hir_id, |this| { + intravisit::walk_const_arg(this, const_arg); + }); + } + fn visit_expr(&mut self, expr: &'hir Expr<'hir>) { self.insert(expr.span, expr.hir_id, Node::Expr(expr)); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index e20b191534427..f990b4ba69b3f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -61,7 +61,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { for (def_id, info) in lctx.children { let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - debug_assert!(matches!(owner, hir::MaybeOwner::Phantom)); + debug_assert!( + matches!(owner, hir::MaybeOwner::Phantom), + "duplicate copy of {def_id:?} in lctx.children" + ); *owner = info; } } @@ -1631,8 +1634,9 @@ impl<'hir> LoweringContext<'_, 'hir> { span, }); let default_ct = self.arena.alloc(hir::ConstArg { + hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(default_ac), - is_desugared_from_effects: true, + is_desugared_from_effects: false, }); let param = hir::GenericParam { def_id, @@ -1657,6 +1661,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }), )), )), + // FIXME(effects) we might not need a default. default: Some(default_ct), is_host_effect: true, synthetic: true, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index dfb27c8cfd980..0f5f4d8023bd1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -54,7 +54,9 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{self as hir}; -use rustc_hir::{GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate}; +use rustc_hir::{ + ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate, +}; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; use rustc_middle::span_bug; @@ -124,7 +126,7 @@ struct LoweringContext<'a, 'hir> { /// they do get their own DefIds. Some of these DefIds have to be created during /// AST lowering, rather than def collection, because we can't tell until after /// name resolution whether an anonymous constant will end up instead being a - /// [`rustc_hir::ConstArgKind::Path`]. However, to compute which generics are + /// [`hir::ConstArgKind::Path`]. However, to compute which generics are /// available to an anonymous constant nested inside another, we need to make /// sure that the parent is recorded as the parent anon const, not the enclosing /// item. So we need to track parent defs differently from HIR owners, since they @@ -2349,64 +2351,146 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + #[instrument(level = "debug", skip(self))] fn lower_const_path_to_const_arg( &mut self, path: &Path, - _res: Res, + res: Res, ty_id: NodeId, span: Span, ) -> &'hir hir::ConstArg<'hir> { - // Construct an AnonConst where the expr is the "ty"'s path. - - let parent_def_id = self.current_def_id_parent; - let node_id = self.next_node_id(); - let span = self.lower_span(span); - - // Add a definition for the in-band const def. - let def_id = self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span); + let ct_kind = match res { + Res::Def(DefKind::ConstParam, _) => { + let qpath = self.lower_qpath( + ty_id, + &None, + path, + ParamMode::Optional, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ); + hir::ConstArgKind::Path(qpath) + } + _ => { + // Construct an AnonConst where the expr is the "ty"'s path. + + let parent_def_id = self.current_def_id_parent; + let node_id = self.next_node_id(); + let span = self.lower_span(span); + + // Add a definition for the in-band const def. + let def_id = + self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span); + let hir_id = self.lower_node_id(node_id); + + let path_expr = Expr { + id: ty_id, + kind: ExprKind::Path(None, path.clone()), + span, + attrs: AttrVec::new(), + tokens: None, + }; - let path_expr = Expr { - id: ty_id, - kind: ExprKind::Path(None, path.clone()), - span, - attrs: AttrVec::new(), - tokens: None, + let ct = self.with_new_scopes(span, |this| { + self.arena.alloc(hir::AnonConst { + def_id, + hir_id, + body: this.with_def_id_parent(def_id, |this| { + this.lower_const_body(path_expr.span, Some(&path_expr)) + }), + span, + }) + }); + hir::ConstArgKind::Anon(ct) + } }; - let ct = self.with_new_scopes(span, |this| { - self.arena.alloc(hir::AnonConst { - def_id, - hir_id: this.lower_node_id(node_id), - body: this.lower_const_body(path_expr.span, Some(&path_expr)), - span, - }) - }); - self.arena.alloc(hir::ConstArg { - kind: hir::ConstArgKind::Anon(ct), + hir_id: self.next_id(), + kind: ct_kind, is_desugared_from_effects: false, }) } + /// 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> { self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon)) } #[instrument(level = "debug", skip(self))] fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> { + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + let expr = if let ExprKind::Block(block, _) = &anon.value.kind + && let [stmt] = block.stmts.as_slice() + && let StmtKind::Expr(expr) = &stmt.kind + && let ExprKind::Path(..) = &expr.kind + { + expr + } else { + &anon.value + }; + let maybe_res = + self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); + debug!("res={:?}", maybe_res); + // FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path + if let Some(res) = maybe_res + && let Res::Def(DefKind::ConstParam, _) = res + && let ExprKind::Path(qself, path) = &expr.kind + { + let qpath = self.lower_qpath( + expr.id, + qself, + path, + ParamMode::Optional, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ); + + return ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Path(qpath), + is_desugared_from_effects: false, + }; + } + let lowered_anon = self.lower_anon_const_to_anon_const(anon); - hir::ConstArg { + ConstArg { + hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon), is_desugared_from_effects: false, } } + /// See [`hir::ConstArg`] for when to use this function vs + /// [`Self::lower_anon_const_to_const_arg`]. fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { - self.arena.alloc(self.with_new_scopes(c.value.span, |this| hir::AnonConst { - def_id: this.local_def_id(c.id), - hir_id: this.lower_node_id(c.id), - body: this.lower_const_body(c.value.span, Some(&c.value)), - span: this.lower_span(c.value.span), + if c.value.is_potential_trivial_const_arg() { + // HACK(min_generic_const_args): see DefCollector::visit_anon_const + // Over there, we guess if this is a bare param and only create a def if + // we think it's not. However we may can guess wrong (see there for example) + // in which case we have to create the def here. + self.create_def( + self.current_def_id_parent, + c.id, + kw::Empty, + DefKind::AnonConst, + c.value.span, + ); + } + + self.arena.alloc(self.with_new_scopes(c.value.span, |this| { + let def_id = this.local_def_id(c.id); + let hir_id = this.lower_node_id(c.id); + hir::AnonConst { + def_id, + hir_id, + body: this.with_def_id_parent(def_id, |this| { + this.lower_const_body(c.value.span, Some(&c.value)) + }), + span: this.lower_span(c.value.span), + } })) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 27218d687e1e7..cd6e1bce35021 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -228,34 +228,51 @@ impl<'hir> PathSegment<'hir> { } } +/// A constant that enters the type system, e.g. through const generics or even +/// array lengths. +/// +/// These are distinct from [`AnonConst`] in part because with the plan for +/// `min_generic_const_args`, arbitrary anonymous constants (like `Foo<{N + 1}>`) +/// will *not* be allowed to use generic parameters. Instead, it will be necessary +/// to add indirection using a free constant that itself has const parameters. +/// +/// So, `ConstArg` (specifically, [`ConstArgKind`]) distinguishes between const args +/// that are [just paths](ConstArgKind::Path) (currently just bare const params) +/// versus const args that are literals or have arbitrary computations (e.g., `{ 1 + 3}`). #[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct ConstArg<'hir> { + #[stable_hasher(ignore)] + pub hir_id: HirId, pub kind: ConstArgKind<'hir>, /// Indicates whether this comes from a `~const` desugaring. pub is_desugared_from_effects: bool, } impl<'hir> ConstArg<'hir> { - pub fn span(&self) -> Span { + pub fn anon_const_hir_id(&self) -> Option { match self.kind { - ConstArgKind::Anon(anon) => anon.span, + ConstArgKind::Anon(ac) => Some(ac.hir_id), + _ => None, } } - // FIXME: convert to field, where ConstArg has its own HirId - pub fn hir_id(&self) -> HirId { - self.anon_const_hir_id() - } - - pub fn anon_const_hir_id(&self) -> HirId { + pub fn span(&self) -> Span { match self.kind { - ConstArgKind::Anon(anon) => anon.hir_id, + ConstArgKind::Path(path) => path.span(), + ConstArgKind::Anon(anon) => anon.span, } } } +/// See [`ConstArg`]. #[derive(Clone, Copy, Debug, HashStable_Generic)] pub enum ConstArgKind<'hir> { + /// **Note:** Currently this is only used for bare const params + /// (`N` where `fn foo(...)`), + /// not paths to any const (`N` where `const N: usize = ...`). + /// + /// However, in the future, we'll be using it for all of those. + Path(QPath<'hir>), Anon(&'hir AnonConst), } @@ -293,7 +310,7 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(l) => l.hir_id, GenericArg::Type(t) => t.hir_id, - GenericArg::Const(c) => c.hir_id(), + GenericArg::Const(c) => c.hir_id, GenericArg::Infer(i) => i.hir_id, } } @@ -1628,8 +1645,9 @@ pub enum ArrayLen<'hir> { impl ArrayLen<'_> { pub fn hir_id(&self) -> HirId { match self { - ArrayLen::Infer(InferArg { hir_id, .. }) => *hir_id, - ArrayLen::Body(ct) => ct.hir_id(), + ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(ConstArg { hir_id, .. }) => { + *hir_id + } } } } @@ -3712,6 +3730,7 @@ pub enum Node<'hir> { Field(&'hir FieldDef<'hir>), AnonConst(&'hir AnonConst), ConstBlock(&'hir ConstBlock), + ConstArg(&'hir ConstArg<'hir>), Expr(&'hir Expr<'hir>), ExprField(&'hir ExprField<'hir>), Stmt(&'hir Stmt<'hir>), @@ -3773,6 +3792,7 @@ impl<'hir> Node<'hir> { Node::Param(..) | Node::AnonConst(..) | Node::ConstBlock(..) + | Node::ConstArg(..) | Node::Expr(..) | Node::Stmt(..) | Node::Block(..) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index db8c704cd2f25..c202ee41e3132 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -732,8 +732,10 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>( visitor: &mut V, const_arg: &'v ConstArg<'v>, ) -> V::Result { - match const_arg.kind { - ConstArgKind::Anon(anon) => visitor.visit_anon_const(anon), + try_visit!(visitor.visit_id(const_arg.hir_id)); + match &const_arg.kind { + ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()), + ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 13aa15cdabdc5..5e23d47327408 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -304,7 +304,6 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { self.tcx.ensure().type_of(param.def_id); if let Some(default) = default { // need to store default and type of default - #[allow(irrefutable_let_patterns)] // FIXME if let hir::ConstArgKind::Anon(ac) = default.kind { self.tcx.ensure().type_of(ac.def_id); } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 22d465c8e62be..690423421b975 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -13,7 +13,7 @@ use rustc_session::lint; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -#[instrument(level = "debug", skip(tcx))] +#[instrument(level = "debug", skip(tcx), ret)] pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; @@ -102,6 +102,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { None } else if tcx.features().generic_const_exprs { let parent_node = tcx.parent_hir_node(hir_id); + debug!(?parent_node); if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node && constant.hir_id == hir_id { @@ -164,13 +165,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } } else { let parent_node = tcx.parent_hir_node(hir_id); + let parent_node = match parent_node { + Node::ConstArg(ca) => tcx.parent_hir_node(ca.hir_id), + _ => parent_node, + }; match parent_node { // HACK(eddyb) this provides the correct generics for repeat // expressions' count (i.e. `N` in `[x; N]`), and explicit // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), // as they shouldn't be able to cause query cycle errors. - Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. }) - if constant.hir_id() == hir_id => + Node::Expr(Expr { kind: ExprKind::Repeat(_, ArrayLen::Body(ct)), .. }) + if ct.anon_const_hir_id() == Some(hir_id) => { Some(parent_did) } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 10c44fb04ae9d..9affd654366f1 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -35,16 +35,32 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { let parent_node_id = tcx.parent_hir_id(hir_id); let parent_node = tcx.hir_node(parent_node_id); - let (generics, arg_idx) = match parent_node { - // Easy case: arrays repeat expressions. - Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. }) - | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) - if constant.hir_id() == hir_id => + match parent_node { + // Anon consts "inside" the type system. + Node::ConstArg(&ConstArg { + hir_id: arg_hir_id, + kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }), + .. + }) if anon_hir_id == hir_id => const_arg_anon_type_of(tcx, arg_hir_id, span), + + // Anon consts outside the type system. + Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) + | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) + if asm.operands.iter().any(|(op, _op_sp)| match op { + hir::InlineAsmOperand::Const { anon_const } + | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id, + _ => false, + }) => { - return tcx.types.usize; + tcx.typeck(def_id).node_type(hir_id) + } + Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { + tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) } + // Sort of affects the type system, but only for the purpose of diagnostics + // so no need for ConstArg. Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => { - let ty = tcx.typeck(def_id).node_type(e.hir_id); + let ty = tcx.typeck(def_id).node_type(tcx.local_def_id_to_hir_id(def_id)); let ty = tcx.fold_regions(ty, |r, _| { if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r } }); @@ -56,24 +72,35 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg }); return ty; } - Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) - if asm.operands.iter().any(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id, - _ => false, - }) => + + _ => Ty::new_error_with_message( + tcx, + span, + format!("unexpected anon const parent in type_of(): {parent_node:?}"), + ), + } +} + +fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> { + use hir::*; + use rustc_middle::ty::Ty; + + let parent_node_id = tcx.parent_hir_id(arg_hir_id); + let parent_node = tcx.hir_node(parent_node_id); + + let (generics, arg_idx) = match parent_node { + // Easy case: arrays repeat expressions. + Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. }) + | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) + if constant.hir_id() == arg_hir_id => { - return tcx.typeck(def_id).node_type(hir_id); - } - Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { - return tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx); + return tcx.types.usize; } Node::GenericParam(&GenericParam { def_id: param_def_id, kind: GenericParamKind::Const { default: Some(ct), .. }, .. - }) if ct.anon_const_hir_id() == hir_id => { + }) if ct.hir_id == arg_hir_id => { return tcx .type_of(param_def_id) .no_bound_vars() @@ -104,7 +131,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { // to a ty::Alias(ty::Projection, `::Assoc<3>`). let item_def_id = tcx .hir() - .parent_owner_iter(hir_id) + .parent_owner_iter(arg_hir_id) .find(|(_, node)| matches!(node, OwnerNode::Item(_))) .unwrap() .0 @@ -124,7 +151,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { args.args .iter() .filter(|arg| arg.is_ty_or_const()) - .position(|arg| arg.hir_id() == hir_id) + .position(|arg| arg.hir_id() == arg_hir_id) }) .unwrap_or_else(|| { bug!("no arg matching AnonConst in segment"); @@ -145,7 +172,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)), .. }) => { - let body_owner = tcx.hir().enclosing_body_owner(hir_id); + let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id); let tables = tcx.typeck(body_owner); // This may fail in case the method/path does not actually exist. // As there is no relevant param for `def_id`, we simply return @@ -163,10 +190,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { args.args .iter() .filter(|arg| arg.is_ty_or_const()) - .position(|arg| arg.hir_id() == hir_id) + .position(|arg| arg.hir_id() == arg_hir_id) }) .unwrap_or_else(|| { - bug!("no arg matching AnonConst in segment"); + bug!("no arg matching ConstArg in segment"); }); (tcx.generics_of(type_dependent_def), idx) @@ -185,18 +212,18 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { | ExprKind::Struct(&QPath::Resolved(_, path), ..), .. }) => { - let body_owner = tcx.hir().enclosing_body_owner(hir_id); + let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id); let _tables = tcx.typeck(body_owner); &*path } Node::Pat(pat) => { - if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) { + if let Some(path) = get_path_containing_arg_in_pat(pat, arg_hir_id) { path } else { return Ty::new_error_with_message( tcx, span, - format!("unable to find const parent for {hir_id} in pat {pat:?}"), + format!("unable to find const parent for {arg_hir_id} in pat {pat:?}"), ); } } @@ -217,14 +244,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { args.args .iter() .filter(|arg| arg.is_ty_or_const()) - .position(|arg| arg.hir_id() == hir_id) + .position(|arg| arg.hir_id() == arg_hir_id) .map(|index| (index, seg)) .or_else(|| { args.constraints .iter() .copied() .filter_map(AssocItemConstraint::ct) - .position(|ct| ct.anon_const_hir_id() == hir_id) + .position(|ct| ct.hir_id == arg_hir_id) .map(|idx| (idx, seg)) }) }) else { @@ -249,7 +276,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { return Ty::new_error_with_message( tcx, span, - format!("unexpected const parent in type_of(): {parent_node:?}"), + format!("unexpected const arg parent in type_of(): {parent_node:?}"), ); } }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 1e89d7201d0c4..6f9c481650b21 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -414,7 +414,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Provide the resolved type of the associated constant to `type_of(AnonConst)`. if let Some(const_arg) = constraint.ct() { - #[allow(irrefutable_let_patterns)] // FIXME if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind { let ty = alias_term .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args)); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index f8b5c86092b9f..b351e31964b56 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -10,8 +10,8 @@ use rustc_errors::{ }; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::GenericArg; -use rustc_hir::{self as hir, ConstArgKind}; +use rustc_hir::{self as hir}; +use rustc_hir::{ConstArgKind, GenericArg}; use rustc_middle::ty::{ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, }; @@ -113,9 +113,12 @@ fn generic_arg_mismatch_err( } } (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => { - let ConstArgKind::Anon(anon) = cnst.kind; - let body = tcx.hir().body(anon.body); - if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind + // FIXME(min_generic_const_args): once ConstArgKind::Path is used for non-params too, + // this should match against that instead of ::Anon + if let ConstArgKind::Anon(anon) = cnst.kind + && let body = tcx.hir().body(anon.body) + && let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = + body.value.kind { if let Res::Def(DefKind::Fn { .. }, id) = path.res { err.help(format!("`{}` is a function item, not a type", tcx.item_name(id))); 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 8dadfbeee6cb6..7b8a03def86bc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -474,7 +474,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id)) .into() } - (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => { + (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { self.lowerer.ct_infer(Some(param), inf.span).into() } (kind, arg) => span_bug!( diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 95bf07c907b81..bbb7d31dbc538 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -87,6 +87,7 @@ impl<'a> State<'a> { Node::Variant(a) => self.print_variant(a), Node::AnonConst(a) => self.print_anon_const(a), Node::ConstBlock(a) => self.print_inline_const(a), + Node::ConstArg(a) => self.print_const_arg(a), Node::Expr(a) => self.print_expr(a), Node::ExprField(a) => self.print_expr_field(a), Node::Stmt(a) => self.print_stmt(a), @@ -993,6 +994,7 @@ impl<'a> State<'a> { fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) { match &const_arg.kind { + ConstArgKind::Path(qpath) => self.print_qpath(qpath, true), ConstArgKind::Anon(anon) => self.print_anon_const(anon), } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 057168c00ac7c..76a6405ff45d0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -8,7 +8,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{self as hir, ConstArg, ConstArgKind}; +use rustc_hir::{self as hir}; use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath}; use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend; use rustc_hir_analysis::hir_ty_lowering::generics::{ @@ -468,22 +468,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn lower_const_arg( &self, - const_arg: &ConstArg<'tcx>, + const_arg: &'tcx hir::ConstArg<'tcx>, param_def_id: DefId, ) -> ty::Const<'tcx> { - match &const_arg.kind { - ConstArgKind::Anon(anon) => { - let did = anon.def_id; - self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id)); - let ct = ty::Const::from_anon_const(self.tcx, did); - self.register_wf_obligation( - ct.into(), - self.tcx.hir().span(anon.hir_id), - ObligationCauseCode::WellFormed(None), - ); - ct - } - } + let ct = + ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id)); + self.register_wf_obligation( + ct.into(), + self.tcx.hir().span(const_arg.hir_id), + ObligationCauseCode::WellFormed(None), + ); + ct } // If the type given by the user has free regions, save it for later, since diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 2f3a6ee601b15..ad59bfa904729 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -912,6 +912,7 @@ impl<'hir> Map<'hir> { Node::Field(field) => field.span, Node::AnonConst(constant) => constant.span, Node::ConstBlock(constant) => self.body(constant.body).value.span, + Node::ConstArg(const_arg) => const_arg.span(), Node::Expr(expr) => expr.span, Node::ExprField(field) => field.span, Node::Stmt(stmt) => stmt.span, @@ -962,7 +963,8 @@ impl<'hir> Map<'hir> { /// Returns the HirId of `N` in `struct Foo` when /// called with the HirId for the `{ ... }` anon const pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option { - match self.tcx.parent_hir_node(anon_const) { + let const_arg = self.tcx.parent_hir_id(anon_const); + match self.tcx.parent_hir_node(const_arg) { Node::GenericParam(GenericParam { def_id: param_id, kind: GenericParamKind::Const { .. }, @@ -1182,6 +1184,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { } Node::AnonConst(_) => node_str("const"), Node::ConstBlock(_) => node_str("const"), + Node::ConstArg(_) => node_str("const"), Node::Expr(_) => node_str("expr"), Node::ExprField(_) => node_str("expr field"), Node::Stmt(_) => node_str("stmt"), diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index a5c4d8b379221..8c465251bae99 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -202,7 +202,6 @@ pub enum FeedConstTy { impl<'tcx> Const<'tcx> { /// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self). #[instrument(skip(tcx), level = "debug")] - #[allow(irrefutable_let_patterns)] pub fn from_const_arg( tcx: TyCtxt<'tcx>, const_arg: &'tcx hir::ConstArg<'tcx>, @@ -215,6 +214,10 @@ impl<'tcx> Const<'tcx> { } match const_arg.kind { + hir::ConstArgKind::Path(qpath) => { + // FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path + Self::from_param(tcx, qpath, const_arg.hir_id) + } hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id), } } @@ -310,16 +313,12 @@ impl<'tcx> Const<'tcx> { } } - if let hir::ExprKind::Path( - qpath @ hir::QPath::Resolved( - _, - &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, - ), - ) = expr.kind + if let hir::ExprKind::Path(hir::QPath::Resolved( + _, + &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, + )) = expr.kind { - // FIXME: once ConstArgKind::Path added, uncomment span_bug and delete return - // span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible") - return Some(Self::from_param(tcx, qpath, expr.hir_id)); + span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible") } None diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 24e3e623ff274..a6dec66449e9f 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -607,7 +607,9 @@ impl<'a, V> ::std::ops::Index for LocalTableInContext<'a, V> { type Output = V; fn index(&self, key: HirId) -> &V { - self.get(key).expect("LocalTableInContext: key not found") + self.get(key).unwrap_or_else(|| { + bug!("LocalTableInContext({:?}): key {:?} not found", self.hir_owner, key) + }) } } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index a4fdb4a0bafaa..1fb942de7343e 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -312,8 +312,19 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); + // HACK(min_generic_const_args): don't create defs for anon consts if we think they will + // later be turned into ConstArgKind::Path's. because this is before resolve is done, we + // may accidentally identify a construction of a unit struct as a param and not create a + // def. we'll then create a def later in ast lowering in this case. the parent of nested + // items will be messed up, but that's ok because there can't be any if we're just looking + // for bare idents. + if constant.value.is_potential_trivial_const_arg() { + visit::walk_anon_const(self, constant) + } else { + let def = + self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); + self.with_parent(def, |this| visit::walk_anon_const(this, constant)); + } } fn visit_expr(&mut self, expr: &'a Expr) { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f071dc6c78486..e77a05dd8e63c 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -672,9 +672,21 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem); } - ty::Array(subty, _) => { + ty::Array(subty, len) => { self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem); - // Note that we handle the len is implicitly checked while walking `arg`. + // Note that the len being WF is implicitly checked while visiting. + // Here we just check that it's of type usize. + let cause = self.cause(ObligationCauseCode::Misc); + self.out.push(traits::Obligation::with_depth( + tcx, + cause, + self.recursion_depth, + self.param_env, + ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType( + len, + tcx.types.usize, + ))), + )); } ty::Pat(subty, _) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a91e5233281cf..ee5c95c3cc32f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -289,6 +289,9 @@ pub(crate) fn clean_const<'tcx>( _cx: &mut DocContext<'tcx>, ) -> Constant { match &constant.kind { + ConstArgKind::Path(qpath) => { + Constant { kind: ConstantKind::Path { path: qpath_to_string(&qpath).into() } } + } ConstArgKind::Anon(anon) => Constant { kind: ConstantKind::Anonymous { body: anon.body } }, } } @@ -1832,7 +1835,6 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T // results in an ICE while manually constructing the constant and using `eval` // does nothing for `ConstKind::Param`. let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No); - #[allow(irrefutable_let_patterns)] // FIXME let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) = const_arg.kind { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a31adc9949a3f..3709953159686 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2395,6 +2395,9 @@ pub(crate) enum ConstantKind { /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified /// by a DefId. So this field must be different from `Extern`. TyConst { expr: Box }, + /// A constant that is just a path (i.e., referring to a const param, free const, etc.). + // FIXME: this is an unfortunate representation. rustdoc's logic around consts needs to be improved. + Path { path: Box }, /// A constant (expression) that's not an item or associated item. These are usually found /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also /// used to define explicit discriminant values for enum variants. @@ -2423,6 +2426,7 @@ impl ConstantKind { pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String { match *self { ConstantKind::TyConst { ref expr } => expr.to_string(), + ConstantKind::Path { ref path } => path.to_string(), ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id), ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body)) @@ -2432,7 +2436,9 @@ impl ConstantKind { pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option { match *self { - ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None, + ConstantKind::TyConst { .. } + | ConstantKind::Path { .. } + | ConstantKind::Anonymous { .. } => None, ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => { print_evaluated_const(tcx, def_id, true, true) } @@ -2441,7 +2447,9 @@ impl ConstantKind { pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool { match *self { - ConstantKind::TyConst { .. } | ConstantKind::Extern { .. } => false, + ConstantKind::TyConst { .. } + | ConstantKind::Extern { .. } + | ConstantKind::Path { .. } => false, ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { is_literal_expr(tcx, body.hir_id) } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 441144d4bd11c..316c1f32d3a2a 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -271,15 +271,14 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { fn const_arg(&self, const_arg: &Binding<&ConstArg<'_>>) { match const_arg.value.kind { - // FIXME: uncomment for ConstArgKind::Path - // ConstArgKind::Path(ref qpath) => { - // bind!(self, qpath); - // chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind"); - // self.qpath(qpath); - // }, + ConstArgKind::Path(ref qpath) => { + bind!(self, qpath); + chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind"); + self.qpath(qpath); + }, ConstArgKind::Anon(anon_const) => { bind!(self, anon_const); - chain!(self, "let ConstArgKind::({anon_const}) = {const_arg}.kind"); + chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind"); self.body(field!(anon_const.body)); }, } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index ae968067850ef..6c6a237a8b161 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -421,7 +421,12 @@ impl HirEqInterExpr<'_, '_, '_> { fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool { match (&left.kind, &right.kind) { + (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), + // Use explicit match for now since ConstArg is undergoing flux. + (ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => { + false + }, } } @@ -1142,6 +1147,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { fn hash_const_arg(&mut self, const_arg: &ConstArg<'_>) { match &const_arg.kind { + ConstArgKind::Path(path) => self.hash_qpath(path), ConstArgKind::Anon(anon) => self.hash_body(anon.body), } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index f562d9787dc7f..8c33c34fa1c5d 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -904,7 +904,6 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { }, ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)), ExprKind::Repeat(x, ArrayLen::Body(len)) => { - #[allow(irrefutable_let_patterns)] // FIXME if let ConstArgKind::Anon(anon_const) = len.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let LitKind::Int(v, _) = const_lit.node @@ -935,7 +934,6 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: & }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String), ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec), ExprKind::Repeat(_, ArrayLen::Body(len)) => { - #[allow(irrefutable_let_patterns)] // FIXME if let ConstArgKind::Anon(anon_const) = len.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let LitKind::Int(v, _) = const_lit.node diff --git a/src/tools/clippy/tests/ui/author/repeat.stdout b/src/tools/clippy/tests/ui/author/repeat.stdout index c2a369610cc1b..d9e3f864f12f4 100644 --- a/src/tools/clippy/tests/ui/author/repeat.stdout +++ b/src/tools/clippy/tests/ui/author/repeat.stdout @@ -1,7 +1,8 @@ if let ExprKind::Repeat(value, length) = expr.kind && let ExprKind::Lit(ref lit) = value.kind && let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node - && let ArrayLen::Body(anon_const) = length + && let ArrayLen::Body(const_arg) = length + && let ConstArgKind::Anon(anon_const) = const_arg.kind && expr1 = &cx.tcx.hir().body(anon_const.body).value && let ExprKind::Lit(ref lit1) = expr1.kind && let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node diff --git a/src/tools/clippy/tests/ui/min_ident_chars.stderr b/src/tools/clippy/tests/ui/min_ident_chars.stderr index 3dd5c9561fd02..7fbd8462fdcce 100644 --- a/src/tools/clippy/tests/ui/min_ident_chars.stderr +++ b/src/tools/clippy/tests/ui/min_ident_chars.stderr @@ -193,5 +193,11 @@ error: this ident consists of a single char LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { | ^ -error: aborting due to 32 previous errors +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:93:41 + | +LL | struct Array([T; N]); + | ^ + +error: aborting due to 33 previous errors diff --git a/tests/crashes/127009.rs b/tests/crashes/127009.rs new file mode 100644 index 0000000000000..74ca14393e4e9 --- /dev/null +++ b/tests/crashes/127009.rs @@ -0,0 +1,11 @@ +//@ known-bug: #127009 + +#![feature(non_lifetime_binders)] + +fn b() +where + for [(); C]: Copy, +{ +} + +fn main() {} diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index f971426723f25..5e3f255756643 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -33,7 +33,7 @@ fn test_stable_mir() -> ControlFlow<()> { // Get all items and split generic vs monomorphic items. let (generic, mono): (Vec<_>, Vec<_>) = items.into_iter().partition(|item| item.requires_monomorphization()); - assert_eq!(mono.len(), 4, "Expected 2 mono functions and one constant"); + assert_eq!(mono.len(), 3, "Expected 3 mono functions"); assert_eq!(generic.len(), 2, "Expected 2 generic functions"); // For all monomorphic items, get the correspondent instances. diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs index fa0b0fdc136ac..e07fa78463c7d 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs @@ -5,9 +5,7 @@ #![feature(with_negative_coherence)] trait Trait {} impl Trait for [(); N] {} -//~^ ERROR: mismatched types impl Trait for [(); N] {} -//~^ ERROR: mismatched types -//~| ERROR: conflicting implementations of trait `Trait` +//~^ ERROR: conflicting implementations of trait `Trait` fn main() {} diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr index d65450845bc12..2087be8e7115d 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr @@ -1,25 +1,11 @@ error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]` - --> $DIR/generic_const_type_mismatch.rs:9:1 + --> $DIR/generic_const_type_mismatch.rs:8:1 | LL | impl Trait for [(); N] {} | ----------------------------------- first implementation here -LL | LL | impl Trait for [(); N] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]` -error[E0308]: mismatched types - --> $DIR/generic_const_type_mismatch.rs:7:34 - | -LL | impl Trait for [(); N] {} - | ^ expected `usize`, found `u8` - -error[E0308]: mismatched types - --> $DIR/generic_const_type_mismatch.rs:9:34 - | -LL | impl Trait for [(); N] {} - | ^ expected `usize`, found `i8` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0308. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs index d5913879191ef..cc2ff9b8dea07 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.rs +++ b/tests/ui/const-generics/bad-subst-const-kind.rs @@ -6,7 +6,7 @@ trait Q { } impl Q for [u8; N] { - //~^ ERROR mismatched types + //~^ ERROR: the constant `N` is not of type `usize` const ASSOC: usize = 1; } diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr index 6725f6762e45d..5c8d9c9036356 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.stderr +++ b/tests/ui/const-generics/bad-subst-const-kind.stderr @@ -1,3 +1,9 @@ +error: the constant `N` is not of type `usize` + --> $DIR/bad-subst-const-kind.rs:8:26 + | +LL | impl Q for [u8; N] { + | ^^^^^^^ expected `usize`, found `u64` + error: the constant `13` is not of type `u64` --> $DIR/bad-subst-const-kind.rs:13:24 | @@ -12,12 +18,5 @@ LL | impl Q for [u8; N] { | | | unsatisfied trait bound introduced here -error[E0308]: mismatched types - --> $DIR/bad-subst-const-kind.rs:8:31 - | -LL | impl Q for [u8; N] { - | ^ expected `usize`, found `u64` - error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs index 6b0d9e047dbc3..8e5e23b233718 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs @@ -7,7 +7,7 @@ trait Q { impl Q for [u8; N] {} //~^ ERROR not all trait items implemented -//~| ERROR mismatched types +//~| ERROR the constant `N` is not of type `usize` pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} //~^ ERROR the constant `13` is not of type `u64` diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr index bb6d650b7ab27..e03580ec007ca 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr @@ -1,3 +1,9 @@ +error: the constant `N` is not of type `usize` + --> $DIR/type_mismatch.rs:8:26 + | +LL | impl Q for [u8; N] {} + | ^^^^^^^ expected `usize`, found `u64` + error[E0046]: not all trait items implemented, missing: `ASSOC` --> $DIR/type_mismatch.rs:8:1 | @@ -29,12 +35,6 @@ LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} | | | implicitly returns `()` as its body has no tail or `return` expression -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:8:31 - | -LL | impl Q for [u8; N] {} - | ^ expected `usize`, found `u64` - error: aborting due to 4 previous errors Some errors have detailed explanations: E0046, E0308. diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index 51cae20df84d4..8b7ee577569a6 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -25,8 +25,8 @@ mod v20 { } impl v17 { - //~^ ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#1} - //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#1} + //~^ ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} pub const fn v21() -> v18 { //~^ ERROR cannot find type `v18` in this scope v18 { _p: () } diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 39f022fbee9db..15d3c47258525 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -72,13 +72,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | -error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl v17 { | ^^ -error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl v17 { diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr index c17a7d5d9fad0..b5eec3046fd9e 100644 --- a/tests/ui/const-generics/issues/issue-88119.stderr +++ b/tests/ui/const-generics/issues/issue-88119.stderr @@ -1,26 +1,32 @@ -error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` - --> $DIR/issue-88119.rs:21:5 +error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{constant#0}` + --> $DIR/issue-88119.rs:19:49 | -LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` +LL | impl const ConstName for &T + | ^^ cannot normalize `<&T as ConstName>::{constant#0}` | -note: required by a bound in `<&T as ConstName>` - --> $DIR/issue-88119.rs:21:10 +note: required for `&T` to implement `ConstName` + --> $DIR/issue-88119.rs:19:35 | +LL | impl const ConstName for &T + | ^^^^^^^^^ ^^ +LL | where LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` + | --------------------- unsatisfied trait bound introduced here -error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` - --> $DIR/issue-88119.rs:28:5 +error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}` + --> $DIR/issue-88119.rs:26:49 | -LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` +LL | impl const ConstName for &mut T + | ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}` | -note: required by a bound in `<&mut T as ConstName>` - --> $DIR/issue-88119.rs:28:10 +note: required for `&mut T` to implement `ConstName` + --> $DIR/issue-88119.rs:26:35 | +LL | impl const ConstName for &mut T + | ^^^^^^^^^ ^^^^^^ +LL | where LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` + | --------------------- unsatisfied trait bound introduced here error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs index e7ae2ea1d5a6a..def4611f94b72 100644 --- a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs +++ b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs @@ -19,6 +19,8 @@ fn bar() {} fn foo() { bar::<{ [1; N] }>(); //~^ ERROR: generic parameters may not be used in const operations + bar::<{ [1; { N + 1 }] }>(); + //~^ ERROR: generic parameters may not be used in const operations } fn main() {} diff --git a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr index 72a6e6977f583..ead6c621d60be 100644 --- a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr +++ b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr @@ -7,5 +7,14 @@ LL | bar::<{ [1; N] }>(); = help: const parameters may only be used as standalone arguments, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to 1 previous error +error: generic parameters may not be used in const operations + --> $DIR/repeat_expr_hack_gives_right_generics.rs:22:19 + | +LL | bar::<{ [1; { N + 1 }] }>(); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs index 90afd23253465..59b77c678e8ce 100644 --- a/tests/ui/const-generics/transmute-fail.rs +++ b/tests/ui/const-generics/transmute-fail.rs @@ -10,11 +10,10 @@ fn foo(v: [[u32;H+1]; W]) -> [[u32; W+1]; H] { } fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - //~^ ERROR mismatched types - //~| ERROR mismatched types + //~^ ERROR the constant `W` is not of type `usize` unsafe { std::mem::transmute(v) - //~^ ERROR cannot transmute between types + //~^ ERROR the constant `W` is not of type `usize` } } diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index b76ec10bd3f21..b40fb23c33158 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -1,3 +1,9 @@ +error: the constant `W` is not of type `usize` + --> $DIR/transmute-fail.rs:12:42 + | +LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^^^^^^^^^^^^^ expected `usize`, found `bool` + error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fail.rs:7:5 | @@ -7,17 +13,14 @@ LL | std::mem::transmute(v) = note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1]) = note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1]) -error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:16:5 +error: the constant `W` is not of type `usize` + --> $DIR/transmute-fail.rs:15:5 | LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ - | - = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) - = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:23:5 + --> $DIR/transmute-fail.rs:22:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -26,7 +29,7 @@ LL | std::mem::transmute(v) = note: target type: `[u32; W * H * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:30:5 + --> $DIR/transmute-fail.rs:29:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -35,7 +38,7 @@ LL | std::mem::transmute(v) = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:37:5 + --> $DIR/transmute-fail.rs:36:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -44,7 +47,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:50:5 + --> $DIR/transmute-fail.rs:49:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -53,7 +56,7 @@ LL | std::mem::transmute(v) = note: target type: `[u32; W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:57:5 + --> $DIR/transmute-fail.rs:56:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -62,7 +65,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:66:5 + --> $DIR/transmute-fail.rs:65:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -71,7 +74,7 @@ LL | std::mem::transmute(v) = note: target type: `[u32; D * W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:75:5 + --> $DIR/transmute-fail.rs:74:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -80,7 +83,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:82:5 + --> $DIR/transmute-fail.rs:81:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -89,7 +92,7 @@ LL | std::mem::transmute(v) = note: target type: `[u8; L * 2]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:89:5 + --> $DIR/transmute-fail.rs:88:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -98,7 +101,7 @@ LL | std::mem::transmute(v) = note: target type: `[u16; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:96:5 + --> $DIR/transmute-fail.rs:95:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -107,7 +110,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:105:5 + --> $DIR/transmute-fail.rs:104:5 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -115,19 +118,6 @@ LL | std::mem::transmute(v) = note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H]) = note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W]) -error[E0308]: mismatched types - --> $DIR/transmute-fail.rs:12:53 - | -LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - | ^ expected `usize`, found `bool` - -error[E0308]: mismatched types - --> $DIR/transmute-fail.rs:12:67 - | -LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - | ^ expected `usize`, found `bool` - -error: aborting due to 15 previous errors +error: aborting due to 14 previous errors -Some errors have detailed explanations: E0308, E0512. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/const-generics/type_mismatch.rs b/tests/ui/const-generics/type_mismatch.rs index daa13277be0a0..8187c785cd1c7 100644 --- a/tests/ui/const-generics/type_mismatch.rs +++ b/tests/ui/const-generics/type_mismatch.rs @@ -1,10 +1,10 @@ fn foo() -> [u8; N] { - bar::() //~ ERROR mismatched types + bar::() //~^ ERROR the constant `N` is not of type `u8` } fn bar() -> [u8; N] {} -//~^ ERROR mismatched types +//~^ ERROR the constant `N` is not of type `usize` //~| ERROR mismatched types fn main() {} diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr index 026999827c0e0..d1bb5c1242f02 100644 --- a/tests/ui/const-generics/type_mismatch.stderr +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -1,3 +1,9 @@ +error: the constant `N` is not of type `usize` + --> $DIR/type_mismatch.rs:6:26 + | +LL | fn bar() -> [u8; N] {} + | ^^^^^^^ expected `usize`, found `u8` + error: the constant `N` is not of type `u8` --> $DIR/type_mismatch.rs:2:11 | @@ -18,18 +24,6 @@ LL | fn bar() -> [u8; N] {} | | | implicitly returns `()` as its body has no tail or `return` expression -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:2:11 - | -LL | bar::() - | ^ expected `u8`, found `usize` - -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:6:31 - | -LL | fn bar() -> [u8; N] {} - | ^ expected `usize`, found `u8` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index 8a7a0981f4154..52d3e003f0ac9 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}` +error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}` --> $DIR/issue-36163.rs:4:9 | LL | B = A, | ^ | -note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`... +note: ...which requires const-evaluating + checking `Foo::{constant#0}`... --> $DIR/issue-36163.rs:4:9 | LL | B = A, @@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`... | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ - = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle + = note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle note: cycle used when checking that `Foo` is well-formed --> $DIR/issue-36163.rs:3:1 | diff --git a/tests/ui/lifetimes/issue-95023.rs b/tests/ui/lifetimes/issue-95023.rs index 7a67297c7632a..bcacd01474fbb 100644 --- a/tests/ui/lifetimes/issue-95023.rs +++ b/tests/ui/lifetimes/issue-95023.rs @@ -9,6 +9,5 @@ impl Fn(&isize) for Error { //~^ ERROR associated function in `impl` without body //~^^ ERROR method `foo` is not a member of trait `Fn` [E0407] //~^^^ ERROR associated type `B` not found for `Self` [E0220] - //~| ERROR associated type `B` not found for `Self` [E0220] } fn main() {} diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr index 310dee5140603..cbc0eeebee113 100644 --- a/tests/ui/lifetimes/issue-95023.stderr +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -56,15 +56,7 @@ error[E0220]: associated type `B` not found for `Self` LL | fn foo(&self) -> Self::B<{ N }>; | ^ help: `Self` has the following associated type: `Output` -error[E0220]: associated type `B` not found for `Self` - --> $DIR/issue-95023.rs:8:44 - | -LL | fn foo(&self) -> Self::B<{ N }>; - | ^ help: `Self` has the following associated type: `Output` - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0046, E0183, E0220, E0229, E0277, E0407. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr index 4d543f6a1559a..7db6a77c77bf6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr @@ -4,20 +4,11 @@ error[E0284]: type annotations needed: cannot normalize `process::{constant#0 LL | fn process(input: [(); T::make(2)]) -> [(); T::make(2)] { | ^^^^^^^^^^^^^^^^ cannot normalize `process::{constant#0}` -error[E0284]: type annotations needed: cannot satisfy `the constant `T::make(P)` can be evaluated` - --> $DIR/const-trait-bounds.rs:18:5 +error[E0284]: type annotations needed: cannot normalize `Struct::field::{constant#0}` + --> $DIR/const-trait-bounds.rs:20:12 | -LL | [u32; T::make(P)]:, - | ^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `T::make(P)` can be evaluated` - | -note: required by a bound in `Struct` - --> $DIR/const-trait-bounds.rs:18:11 - | -LL | struct Struct - | ------ required by a bound in this struct -LL | where -LL | [u32; T::make(P)]:, - | ^^^^^^^^^^ required by this bound in `Struct` +LL | field: [u32; T::make(P)], + | ^^^^^^^^^^^^^^^^^ cannot normalize `Struct::field::{constant#0}` error[E0284]: type annotations needed: cannot normalize `process::{constant#1}` --> $DIR/const-trait-bounds.rs:13:5 diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs index 59a015da84ebd..fb962ad24bf93 100644 --- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs @@ -14,6 +14,5 @@ struct Wrapper::Type> {} impl Wrapper {} //~^ ERROR the constant `C` is not of type `::Type` -//~^^ ERROR mismatched types fn main() {} diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr index 71d4277275fee..7094ee8c67ca0 100644 --- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr @@ -20,17 +20,5 @@ note: required by a const generic parameter in `Wrapper` LL | struct Wrapper::Type> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Wrapper` -error[E0308]: mismatched types - --> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:15:30 - | -LL | impl Wrapper {} - | ^ expected associated type, found `usize` - | - = note: expected associated type `::Type` - found type `usize` - = help: consider constraining the associated type `::Type` to `usize` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs index f89a463bc5805..a0ee771441772 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs @@ -6,7 +6,6 @@ struct S; impl Copy for S {} -//~^ ERROR: mismatched types impl Copy for S {} //~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>` diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr index 1dac58e1f694e..2953bc95917c9 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr @@ -1,19 +1,11 @@ error[E0119]: conflicting implementations of trait `Copy` for type `S<_>` - --> $DIR/bad-const-wf-doesnt-specialize.rs:10:1 + --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1 | LL | impl Copy for S {} | -------------------------------- first implementation here -LL | LL | impl Copy for S {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>` -error[E0308]: mismatched types - --> $DIR/bad-const-wf-doesnt-specialize.rs:8:31 - | -LL | impl Copy for S {} - | ^ expected `usize`, found `i32` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0308. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index a7a612a8a9ea7..b27f769ba34f4 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -123,15 +123,15 @@ hir-stats Lifetime 24 ( 0.3%) 1 24 hir-stats Mod 32 ( 0.4%) 1 32 hir-stats ExprField 40 ( 0.4%) 1 40 hir-stats TraitItemRef 56 ( 0.6%) 2 28 +hir-stats GenericArg 64 ( 0.7%) 4 16 +hir-stats - Type 16 ( 0.2%) 1 +hir-stats - Lifetime 48 ( 0.5%) 3 hir-stats Local 64 ( 0.7%) 1 64 hir-stats Param 64 ( 0.7%) 2 32 hir-stats Body 72 ( 0.8%) 3 24 hir-stats InlineAsm 72 ( 0.8%) 1 72 hir-stats ImplItemRef 72 ( 0.8%) 2 36 hir-stats Arm 80 ( 0.9%) 2 40 -hir-stats GenericArg 96 ( 1.1%) 4 24 -hir-stats - Type 24 ( 0.3%) 1 -hir-stats - Lifetime 72 ( 0.8%) 3 hir-stats FieldDef 96 ( 1.1%) 2 48 hir-stats Stmt 96 ( 1.1%) 3 32 hir-stats - Let 32 ( 0.4%) 1 @@ -155,8 +155,8 @@ hir-stats Generics 560 ( 6.2%) 10 56 hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1 -hir-stats - Path 624 ( 6.9%) 13 -hir-stats Expr 768 ( 8.5%) 12 64 +hir-stats - Path 624 ( 7.0%) 13 +hir-stats Expr 768 ( 8.6%) 12 64 hir-stats - Path 64 ( 0.7%) 1 hir-stats - Struct 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1 @@ -174,5 +174,5 @@ hir-stats - Use 352 ( 3.9%) 4 hir-stats Path 1_240 (13.8%) 31 40 hir-stats PathSegment 1_920 (21.4%) 40 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_992 +hir-stats Total 8_960 hir-stats diff --git a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs deleted file mode 100644 index bbae67f0bad41..0000000000000 --- a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(non_lifetime_binders)] -//~^ WARN the feature `non_lifetime_binders` is incomplete - -fn b() -where - for [(); C]: Copy, - //~^ ERROR cannot capture late-bound const parameter in constant -{ -} - -fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr deleted file mode 100644 index 4e0441c1c7d02..0000000000000 --- a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr +++ /dev/null @@ -1,19 +0,0 @@ -warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-late-ct-in-anon.rs:1:12 - | -LL | #![feature(non_lifetime_binders)] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #108185 for more information - = note: `#[warn(incomplete_features)]` on by default - -error: cannot capture late-bound const parameter in constant - --> $DIR/capture-late-ct-in-anon.rs:6:30 - | -LL | for [(); C]: Copy, - | -------------- ^ - | | - | parameter defined here - -error: aborting due to 1 previous error; 1 warning emitted - diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs index 0695d7d409fe0..20bd7917e5322 100644 --- a/tests/ui/transmutability/issue-101739-1.rs +++ b/tests/ui/transmutability/issue-101739-1.rs @@ -7,7 +7,6 @@ mod assert { where Dst: BikeshedIntrinsicFrom, //~ ERROR cannot find type `Dst` in this scope //~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume` - //~| ERROR: mismatched types { } } diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr index 6f79bf7b42468..ba18a980f4d0a 100644 --- a/tests/ui/transmutability/issue-101739-1.stderr +++ b/tests/ui/transmutability/issue-101739-1.stderr @@ -13,13 +13,6 @@ LL | Dst: BikeshedIntrinsicFrom, note: required by a const generic parameter in `BikeshedIntrinsicFrom` --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL -error[E0308]: mismatched types - --> $DIR/issue-101739-1.rs:8:41 - | -LL | Dst: BikeshedIntrinsicFrom, - | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0308, E0412. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs index 1c0bd29d70791..8b36bf3dcb195 100644 --- a/tests/ui/transmutability/issue-101739-2.rs +++ b/tests/ui/transmutability/issue-101739-2.rs @@ -16,7 +16,7 @@ mod assert { where Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied Src, - ASSUME_ALIGNMENT, //~ ERROR: mismatched types + ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_VALIDITY, ASSUME_VISIBILITY, diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr index 38912696c18e3..519a374dc2294 100644 --- a/tests/ui/transmutability/issue-101739-2.stderr +++ b/tests/ui/transmutability/issue-101739-2.stderr @@ -9,13 +9,6 @@ LL | | ASSUME_VALIDITY, LL | | ASSUME_VISIBILITY, | |_____________________________- help: remove these generic arguments -error[E0308]: mismatched types - --> $DIR/issue-101739-2.rs:19:13 - | -LL | ASSUME_ALIGNMENT, - | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0107, E0308. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs index 193544ebd3fef..9fc249198d03d 100644 --- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs +++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs @@ -5,7 +5,7 @@ trait Trait { - fn func() -> [ (); N ]; //~ ERROR mismatched types + fn func() -> [ (); N ]; //~ ERROR the constant `N` is not of type `usize` } struct S {} diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr index 16aaf0615ed22..bff926a2081ab 100644 --- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr +++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr @@ -4,11 +4,11 @@ error[E0308]: mismatched types LL | fn func() -> [ (); { () }] { | ^^ expected `usize`, found `()` -error[E0308]: mismatched types - --> $DIR/const-in-impl-fn-return-type.rs:8:38 +error: the constant `N` is not of type `usize` + --> $DIR/const-in-impl-fn-return-type.rs:8:32 | LL | fn func() -> [ (); N ]; - | ^ expected `usize`, found `u32` + | ^^^^^^^^^ expected `usize`, found `u32` error: aborting due to 2 previous errors From 2e4a0e37e68beded4bdc473ecd8e94899e2eccc2 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 17 Jul 2024 20:07:50 -0700 Subject: [PATCH 09/10] Clarify docs explaining purpose of `ConstArg` Co-authored-by: Boxy --- compiler/rustc_hir/src/hir.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index cd6e1bce35021..bf773f2d48793 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -228,17 +228,16 @@ impl<'hir> PathSegment<'hir> { } } -/// A constant that enters the type system, e.g. through const generics or even -/// array lengths. +/// A constant that enters the type system, used for arguments to const generics (e.g. array lengths). /// -/// These are distinct from [`AnonConst`] in part because with the plan for -/// `min_generic_const_args`, arbitrary anonymous constants (like `Foo<{N + 1}>`) -/// will *not* be allowed to use generic parameters. Instead, it will be necessary -/// to add indirection using a free constant that itself has const parameters. +/// These are distinct from [`AnonConst`] as anon consts in the type system are not allowed +/// to use any generic parameters, therefore we must represent `N` differently. Additionally +/// future designs for supporting generic parameters in const arguments will likely not use +/// an anon const based design. /// /// So, `ConstArg` (specifically, [`ConstArgKind`]) distinguishes between const args /// that are [just paths](ConstArgKind::Path) (currently just bare const params) -/// versus const args that are literals or have arbitrary computations (e.g., `{ 1 + 3}`). +/// versus const args that are literals or have arbitrary computations (e.g., `{ 1 + 3 }`). #[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct ConstArg<'hir> { #[stable_hasher(ignore)] From c8457e60e8a1bbade7f8aa34d3646c392a4237b6 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 17 Jul 2024 20:20:18 -0700 Subject: [PATCH 10/10] Remove some unintended changes to imports --- .../rustc_hir_analysis/src/hir_ty_lowering/generics.rs | 6 +++--- compiler/rustc_hir_pretty/src/lib.rs | 7 ++++--- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- src/librustdoc/clean/mod.rs | 8 +++++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index b351e31964b56..abe2cff321f76 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -8,10 +8,10 @@ use rustc_ast::ast::ParamKindOrd; use rustc_errors::{ codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, }; +use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir}; -use rustc_hir::{ConstArgKind, GenericArg}; +use rustc_hir::GenericArg; use rustc_middle::ty::{ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, }; @@ -115,7 +115,7 @@ fn generic_arg_mismatch_err( (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => { // FIXME(min_generic_const_args): once ConstArgKind::Path is used for non-params too, // this should match against that instead of ::Anon - if let ConstArgKind::Anon(anon) = cnst.kind + if let hir::ConstArgKind::Anon(anon) = cnst.kind && let body = tcx.hir().body(anon.body) && let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index bbb7d31dbc538..db5eba0d9ebaf 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -10,10 +10,11 @@ use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; use rustc_ast_pretty::pprust::{Comments, PrintState}; -use rustc_hir::{self as hir, ConstArgKind}; +use rustc_hir as hir; use rustc_hir::{ - BindingMode, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId, - LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TraitBoundModifier, + BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind, + HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, + TraitBoundModifier, }; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, Ident, Symbol}; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 76a6405ff45d0..cc2c1a302f58b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -5,10 +5,10 @@ use crate::rvalue_scopes; use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey}; +use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{self as hir}; use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath}; use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend; use rustc_hir_analysis::hir_ty_lowering::generics::{ diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ee5c95c3cc32f..e3c4602212c5b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -36,10 +36,10 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry}; use rustc_errors::{codes::*, struct_span_code_err, FatalError}; +use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::PredicateOrigin; -use rustc_hir::{self as hir, ConstArgKind}; use rustc_hir_analysis::lower_ty; use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; @@ -289,10 +289,12 @@ pub(crate) fn clean_const<'tcx>( _cx: &mut DocContext<'tcx>, ) -> Constant { match &constant.kind { - ConstArgKind::Path(qpath) => { + hir::ConstArgKind::Path(qpath) => { Constant { kind: ConstantKind::Path { path: qpath_to_string(&qpath).into() } } } - ConstArgKind::Anon(anon) => Constant { kind: ConstantKind::Anonymous { body: anon.body } }, + hir::ConstArgKind::Anon(anon) => { + Constant { kind: ConstantKind::Anonymous { body: anon.body } } + } } }