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 666e7763e62..4d4a6fa8a60 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 218fa974022..f04d0e7bece 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 24748d2d009..8315ba6fd84 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 8315ba6fd84..e165b9874e1 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 3bd7b300758..08abcf6e214 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 9bb3245ae05..19582459b0e 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 cad7870a0a1..43aa54254b5 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 b1c77db9f37..f8b5c86092b 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 a665306f2c6..0d2d83bc43f 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 5105d60ae18..f210736a125 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 6da3f1dd114..594d05e602d 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 e574fde14fb..e70431a68ff 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 c1f5cd45dc8..fa23f120468 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 0720efebf97..fb7529d93ed 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 a0e28d2f55c..ced43655b15 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 8706cec5d38..437f563cabd 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 4d4a6fa8a60..269e045cf26 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 0ad23b53566..311fcac82c2 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 e165b9874e1..cdb16ef356d 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_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { + 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_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 08abcf6e214..8a9f5b10b79 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 0d2d83bc43f..62d12756832 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 32d01d07c17..6eae30dc3e4 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 9a4562e9cfc..bd073cd891f 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 cdb16ef356d..3ff220b8a29 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 8a9f5b10b79..f74a1593518 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 19582459b0e..ea67bfdb86c 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 974dd415f46..d628ed955c6 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 a1feef9e15b..1e89d7201d0 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 5e595488ea7..706afdb9d3a 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 62d12756832..26f9820b872 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 f210736a125..8ebd9cb1667 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 ced43655b15..6849a631010 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 3ff220b8a29..fd55cbf64f2 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 f74a1593518..f996b225290 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 ea67bfdb86c..848d2ca99cb 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 26f9820b872..8dadfbeee6c 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 8ebd9cb1667..eeb711f9e89 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 035a3429ed7..e957330d9a1 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 594d05e602d..057168c00ac 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 ddd5818203c..e8b37604f6b 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 6849a631010..7172f9d41cb 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 c9bfc9c85d9..d94b0cce948 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 462084e96a8..db8c63892b8 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 e9d69407df8..441144d4bd1 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 437f563cabd..ae968067850 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 bdb3b5e45c4..f562d9787dc 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 44f37b5533a..b98a33c4b18 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 311fcac82c2..e20b1915344 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 fd55cbf64f2..dfb27c8cfd9 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 f996b225290..27218d687e1 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 848d2ca99cb..db8c704cd2f 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 e0aad299163..13aa15cdabd 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 b89d034fc2e..9e430c83e20 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 43aa54254b5..7930f54038d 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 d628ed955c6..10c44fb04ae 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 eeb711f9e89..95bf07c907b 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 6eae30dc3e4..a5c4d8b3792 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 7172f9d41cb..a91e5233281 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 | 125 ++++++++------- compiler/rustc_ast_lowering/src/index.rs | 10 ++ compiler/rustc_ast_lowering/src/item.rs | 9 +- compiler/rustc_ast_lowering/src/lib.rs | 146 ++++++++++++++---- 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 | 42 ++--- .../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, 542 insertions(+), 415 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 269e045cf26..de0874af934 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 f04d0e7bece..d870f9fe0ae 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) }; + 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, - ); + // 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 b98a33c4b18..23729124e21 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 e20b1915344..f990b4ba69b 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 dfb27c8cfd9..0f5f4d8023b 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 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); + 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); + // 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 27218d687e1..cd6e1bce350 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 db8c704cd2f..c202ee41e31 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 13aa15cdabd..5e23d473274 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 22d465c8e62..690423421b9 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 10c44fb04ae..9affd654366 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 1e89d7201d0..6f9c481650b 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 f8b5c86092b..b351e31964b 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 8dadfbeee6c..7b8a03def86 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 95bf07c907b..bbb7d31dbc5 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 057168c00ac..76a6405ff45 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 2f3a6ee601b..ad59bfa9047 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 a5c4d8b3792..8c465251bae 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 24e3e623ff2..a6dec66449e 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 a4fdb4a0baf..1fb942de734 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 f071dc6c784..e77a05dd8e6 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 a91e5233281..ee5c95c3cc3 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 a31adc9949a..37099531596 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 441144d4bd1..316c1f32d3a 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 ae968067850..6c6a237a8b1 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 f562d9787dc..8c33c34fa1c 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 c2a369610cc..d9e3f864f12 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 3dd5c9561fd..7fbd8462fdc 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 00000000000..74ca14393e4 --- /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 f971426723f..5e3f2557566 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 fa0b0fdc136..e07fa78463c 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 d65450845bc..2087be8e711 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: aborting due to 1 previous error -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 - -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 d5913879191..cc2ff9b8dea 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 6725f6762e4..5c8d9c90363 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 6b0d9e047db..8e5e23b2337 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 bb6d650b7ab..e03580ec007 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 51cae20df84..8b7ee577569 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 39f022fbee9..15d3c472585 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 c17a7d5d9fa..b5eec3046fd 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 | impl const ConstName for &T + | ^^ cannot normalize `<&T as ConstName>::{constant#0}` + | +note: required for `&T` to implement `ConstName` + --> $DIR/issue-88119.rs:19:35 + | +LL | impl const ConstName for &T + | ^^^^^^^^^ ^^ +LL | where LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` - | -note: required by a bound in `<&T as ConstName>` - --> $DIR/issue-88119.rs:21:10 - | -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 | impl const ConstName for &mut T + | ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}` + | +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::()]:, - | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` - | -note: required by a bound in `<&mut T as ConstName>` - --> $DIR/issue-88119.rs:28:10 - | -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 e7ae2ea1d5a..def4611f94b 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 72a6e6977f5..ead6c621d60 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 90afd232534..59b77c678e8 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 b76ec10bd3f..b40fb23c331 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: aborting due to 14 previous errors -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 - -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 daa13277be0..8187c785cd1 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 026999827c0..d1bb5c1242f 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 8a7a0981f41..52d3e003f0a 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 7a67297c763..bcacd01474f 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 310dee51406..cbc0eeebee1 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 4d543f6a155..7db6a77c77b 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 59a015da84e..fb962ad24bf 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 71d4277275f..7094ee8c67c 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 2 previous errors -error: aborting due to 3 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 f89a463bc58..a0ee7714417 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 1dac58e1f69..2953bc95917 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 1 previous error -error: aborting due to 2 previous errors - -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 a7a612a8a9e..b27f769ba34 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 bbae67f0bad..00000000000 --- 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 4e0441c1c7d..00000000000 --- 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 0695d7d409f..20bd7917e53 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 6f79bf7b424..ba18a980f4d 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 2 previous errors -error: aborting due to 3 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 1c0bd29d707..8b36bf3dcb1 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 38912696c18..519a374dc22 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 1 previous error -error: aborting due to 2 previous errors - -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 193544ebd3f..9fc249198d0 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 16aaf0615ed..bff926a2081 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 cd6e1bce350..bf773f2d487 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 b351e31964b..abe2cff321f 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 bbb7d31dbc5..db5eba0d9eb 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 76a6405ff45..cc2c1a302f5 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 ee5c95c3cc3..e3c4602212c 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 } } + } } }