diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index e60e11f11df9f..9686729ad6eb7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -642,6 +642,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ( GenericArgKind::Lifetime(_) | GenericArgKind::Type(_) + | GenericArgKind::Constness(_) | GenericArgKind::Const(_), _, ) => { diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 7c1fa28b8dfcc..bd23350557479 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -381,6 +381,7 @@ fn check_opaque_type_parameter_valid( matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)) } GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), + GenericArgKind::Constness(_) => false, }; if arg_is_param { diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 55c0bf05b4873..30c77a935c062 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -93,7 +93,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.prove_predicates( Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, - constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, }))), locations, diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 3f9c0cecccc68..5afea31c047e7 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -126,7 +126,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { .type_must_outlive(origin, t1, r2); } - GenericArgKind::Const(_) => { + GenericArgKind::Constness(_) | GenericArgKind::Const(_) => { // Consts cannot outlive one another, so we // don't need to handle any relations here. } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index cf2140097e6da..7d5d1d02c040f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2026,6 +2026,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let trait_ref = ty::TraitRef { def_id: tcx .require_lang_item(LangItem::CoerceUnsized, Some(self.last_span)), + // TODO: pick constness arg from context substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]), }; @@ -2603,7 +2604,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { (outlives_requirements.category, outlives_requirements.blame_span), )) } - GenericArgKind::Type(_) | GenericArgKind::Const(_) => None, + GenericArgKind::Type(_) + | GenericArgKind::Const(_) + | GenericArgKind::Constness(_) => None, } }) .collect(); diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index b18976302b4ff..fc74f66c48c8f 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -226,7 +226,6 @@ pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { - assert!(key.param_env.is_const()); // see comment in eval_to_allocation_raw_provider for what we're doing here if key.param_env.reveal() == Reveal::All { let mut key = key; @@ -261,7 +260,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { - assert!(key.param_env.is_const()); // Because the constant is computed twice (once per value of `Reveal`), we are at risk of // reporting the same error twice here. To resolve this, we check whether we can evaluate the // constant in the more restrictive `Reveal::UserFacing`, which most likely already was diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 2e47cf8921073..8854da8b2df66 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -924,7 +924,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { self.param_env }; - let param_env = param_env.with_const(); // Use a precise span for better cycle errors. let val = self.tcx.at(self.cur_span()).eval_to_allocation_raw(param_env.and(gid))?; self.raw_const_to_mplace(val) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 39fabd17c5271..69d8d3f285e95 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -346,7 +346,9 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { // No constraints on lifetimes or constants, except potentially // constants' types, but `walk` will get to them as well. - GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue, + GenericArgKind::Constness(_) + | GenericArgKind::Lifetime(_) + | GenericArgKind::Const(_) => continue, }; match *ty.kind() { @@ -720,10 +722,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { return; } - let trait_ref = TraitRef::from_method(tcx, trait_id, substs); + let trait_ref = TraitRef::from_method(tcx, trait_id, substs).with_const(tcx); let poly_trait_pred = Binder::dummy(TraitPredicate { trait_ref, - constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }); let obligation = @@ -735,7 +736,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { }); match implsrc { - Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => { + Ok(Some(ImplSource::Param(_, ty::ConstnessArg::Const))) => { debug!( "const_trait_impl: provided {:?} via where-clause in {:?}", trait_ref, param_env diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 1d083b0bf8268..8c90974d50e4a 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::{ suggest_constraining_type_param, Adt, Closure, DefIdTree, FnDef, FnPtr, Param, TraitPredicate, Ty, }; -use rustc_middle::ty::{Binder, BoundConstness, ImplPolarity, TraitRef}; +use rustc_middle::ty::{Binder, ImplPolarity, TraitRef}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{BytePos, Pos, Span, Symbol}; @@ -150,7 +150,6 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { param_env, Binder::dummy(TraitPredicate { trait_ref, - constness: BoundConstness::NotConst, polarity: ImplPolarity::Positive, }), ); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 29464cf8c4e4f..27e8e848cdc5e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -161,9 +161,8 @@ impl Qualif for NeedsNonConstDrop { ty::Binder::dummy(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: destruct, - substs: cx.tcx.mk_substs_trait(ty, &[]), + substs: cx.tcx.mk_substs_trait(ty, &[ty::ConstnessArg::Const.into()]), }, - constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }), ); @@ -177,8 +176,7 @@ impl Qualif for NeedsNonConstDrop { if !matches!( impl_src, - ImplSource::ConstDestruct(_) - | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) + ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::ConstnessArg::Const) ) { // If our const destruct candidate is not ConstDestruct or implied by the param env, // then it's bad diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 7120d5ad93455..61df4637f19ed 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -466,6 +466,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { opt_values[b] = Some(*original_value); } } + GenericArgKind::Constness(_) => {} } } @@ -571,6 +572,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // encounter this branch. span_bug!(cause.span, "unexpected const outlives {:?}", predicate); } + GenericArgKind::Constness(_) => { + span_bug!(cause.span, "unexpected constness outlives {:?}", predicate); + } }; let predicate = predicate.rebind(atom).to_predicate(self.tcx); diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 8bf1de34a9b5c..5602598632e2d 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -767,6 +767,15 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { _ => relate::super_relate_consts(self, c, c), } } + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + assert_eq!(a, b); + Ok(a) + } } pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> { @@ -998,4 +1007,12 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { _ => relate::super_relate_consts(self, c, c), } } + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + assert_eq!(a, b); + Ok(a) + } } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 3b1798ca73746..033e9a7224c4b 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -160,6 +160,17 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { } Ok(a) } + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + match (a, b) { + (ty::ConstnessArg::Infer, x) | (x, ty::ConstnessArg::Infer) => Ok(x), + _ => relate::super_relate_constness(self, a, b), + } + } } impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 4d29fc469462c..7c4e7214e1ebf 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -292,6 +292,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), + // TODO ? + GenericArgKind::Constness(_) => bug!("unexpected constness arg"), } } @@ -616,7 +618,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { /// Computes cost for the given source. /// - /// Sources with a small cost are prefer and should result + /// Sources with a small cost are preferred and should result /// in a clearer and idiomatic suggestion. fn source_cost(&self, source: &InferSource<'tcx>) -> usize { #[derive(Clone, Copy)] @@ -629,6 +631,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { GenericArgKind::Lifetime(_) => 0, // erased GenericArgKind::Type(ty) => self.ty_cost(ty), GenericArgKind::Const(_) => 3, // some non-zero value + GenericArgKind::Constness(_) => 1, } } fn ty_cost(self, ty: Ty<'tcx>) -> usize { @@ -746,6 +749,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } match inner.unpack() { GenericArgKind::Lifetime(_) => {} + GenericArgKind::Constness(_) => {} GenericArgKind::Type(ty) => { if matches!(ty.kind(), ty::Opaque(..) | ty::Closure(..) | ty::Generator(..)) { // Opaque types can't be named by the user right now. diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 1570a08f3ca8b..7fb51f96cd83f 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -7,7 +7,7 @@ use super::Subtype; use crate::infer::combine::ConstEquateRelation; use crate::traits::{ObligationCause, PredicateObligation}; -use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt}; /// "Greatest lower bound" (common subtype) @@ -110,6 +110,15 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> { Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?)) } } + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + // TODO. + relate::super_relate_constness(self, a, b) + } } impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index 9f96d52c85034..954656f2532b6 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -7,7 +7,7 @@ use super::Subtype; use crate::infer::combine::ConstEquateRelation; use crate::traits::{ObligationCause, PredicateObligation}; -use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::relate::{super_relate_constness, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt}; /// "Least upper bound" (common supertype) @@ -110,6 +110,14 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> { Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?)) } } + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + super_relate_constness(self, a, b) + } } impl<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 28f037cc61a76..6e763f8189509 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1155,7 +1155,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.next_region_var_in_universe(RegionVariableOrigin::Nll(origin), universe) } - pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> GenericArg<'tcx> { + pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef, constness: Option) -> GenericArg<'tcx> { match param.kind { GenericParamDefKind::Lifetime => { // Create a region inference variable for the given @@ -1199,13 +1199,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }); self.tcx.mk_const_var(const_var_id, self.tcx.type_of(param.def_id)).into() } + GenericParamDefKind::Constness => constness.unwrap_or(ty::ConstnessArg::Infer).into(), } } /// Given a set of generics defined on a type or impl, returns a substitution mapping each /// type/region parameter to a fresh inference variable. pub fn fresh_substs_for_item(&self, span: Span, def_id: DefId) -> SubstsRef<'tcx> { - InternalSubsts::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param)) + InternalSubsts::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param, None)) } /// Returns `true` if errors have been reported since this infcx was @@ -1752,7 +1753,7 @@ impl<'tcx> TyOrConstInferVar<'tcx> { match arg.unpack() { GenericArgKind::Type(ty) => Self::maybe_from_ty(ty), GenericArgKind::Const(ct) => Self::maybe_from_const(ct), - GenericArgKind::Lifetime(_) => None, + GenericArgKind::Lifetime(_) | GenericArgKind::Constness(_) => None, } } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index bab4f3e9e362f..2b1c376a46af2 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -784,6 +784,15 @@ where Ok(a) } + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + // TODO. + relate::super_relate_constness(self, a, b) + } } impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D> @@ -1077,4 +1086,13 @@ where self.first_free_index.shift_out(1); Ok(a.rebind(result)) } + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + // TODO + relate::super_relate_constness(self, a, b) + } } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index f11701bba6f43..c7821422c245b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -379,7 +379,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .iter() .filter_map(|arg| match arg.unpack() { GenericArgKind::Lifetime(r) => Some(r), - GenericArgKind::Type(_) | GenericArgKind::Const(_) => None, + GenericArgKind::Type(_) + | GenericArgKind::Const(_) + | GenericArgKind::Constness(_) => None, }) .chain(std::iter::once(self.tcx.lifetimes.re_static)) .collect(), diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 7234660dbcd32..b4734cc931478 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -88,6 +88,8 @@ fn compute_components<'tcx>( GenericArgKind::Const(_) => { compute_components_recursive(tcx, child, out, visited); } + // TODO ? + GenericArgKind::Constness(_) => {} } } } @@ -210,6 +212,8 @@ fn compute_components_recursive<'tcx>( GenericArgKind::Const(_) => { compute_components_recursive(tcx, child, out, visited); } + // TODO ? + GenericArgKind::Constness(_) => {} } } } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 59cf39abe6440..70b585ecaa542 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -391,6 +391,8 @@ where GenericArgKind::Const(_) => { // Const parameters don't impose constraints. } + // TODO ? + GenericArgKind::Constness(_) => {} } } diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index 772e297b7b445..1f13828eb99a9 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -204,4 +204,13 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { self.pattern_depth.shift_out(1); result } + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + // TODO + relate::super_relate_constness(self, a, b) + } } diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 86b025dce5eda..7a099d27ecd8b 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -67,6 +67,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)), GenericArgKind::Lifetime(_) => None, GenericArgKind::Const(_) => Some(self.recursive_bound(child, visited)), + // TODO ? + GenericArgKind::Constness(_) => None, }) .filter(|bound| { // Remove bounds that must hold, since they are not interesting. @@ -208,6 +210,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { if !lt.is_late_bound() { Some(VerifyBound::OutlivedBy(lt)) } else { None } } GenericArgKind::Const(_) => Some(self.recursive_bound(child, visited)), + // TODO ? + GenericArgKind::Constness(_) => None, }) .filter(|bound| { // Remove bounds that must hold, since they are not interesting. diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index b27571275b733..61f6100b83899 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -4,7 +4,7 @@ use super::SubregionOrigin; use crate::infer::combine::ConstEquateRelation; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::traits::Obligation; -use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::relate::{self, Cause, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::TyVar; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; @@ -201,6 +201,21 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { self.fields.higher_ranked_sub(a, b, self.a_is_expected)?; Ok(a) } + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + trace!(?a, ?b); + match (a, b) { + (ty::ConstnessArg::Const, _) => Ok(a), + (a, ty::ConstnessArg::Infer) => Ok(a), + (ty::ConstnessArg::Infer, b) => Ok(b), + (a, ty::ConstnessArg::Not) => Ok(a), + _ => relate::super_relate_constness(self, a, b), + } + } } impl<'tcx> ConstEquateRelation<'tcx> for Sub<'_, '_, 'tcx> { diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 736278ba0d346..fafedf4603d23 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -34,7 +34,7 @@ pub trait TraitEngine<'tcx>: 'tcx { cause, recursion_depth: 0, param_env, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(infcx.tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(infcx.tcx), }, ); } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 4df4de21a0f07..a2bcb8ff1e363 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -70,14 +70,6 @@ impl<'tcx> PredicateObligation<'tcx> { } impl<'tcx> TraitObligation<'tcx> { - /// Returns `true` if the trait predicate is considered `const` in its ParamEnv. - pub fn is_const(&self) -> bool { - match (self.predicate.skip_binder().constness, self.param_env.constness()) { - (ty::BoundConstness::ConstIfConst, hir::Constness::Const) => true, - _ => false, - } - } - pub fn derived_cause( &self, variant: impl FnOnce(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 5d22f9f972e10..cb4a16204842a 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -228,6 +228,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { /// type information (in which case, the "fully resolved" key will /// be different). pub fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) { + debug!(?key, "ambiguous"); let fresh = self.map().insert(key, ProjectionCacheEntry::Ambiguous); assert!(!fresh, "never started projecting `{:?}`", key); } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 674c75fdee561..985517e9575dd 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -75,14 +75,15 @@ pub fn elaborate_trait_ref<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, ) -> Elaborator<'tcx> { - elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx))) + elaborate_predicates(tcx, std::iter::once(trait_ref.to_predicate(tcx))) } pub fn elaborate_trait_refs<'tcx>( tcx: TyCtxt<'tcx>, trait_refs: impl Iterator>, ) -> Elaborator<'tcx> { - let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate(tcx)); + let predicates = + trait_refs.map(|trait_ref| trait_ref.to_poly_trait_predicate().to_predicate(tcx)); elaborate_predicates(tcx, predicates) } diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index a6912653368b5..4144959b61eff 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -58,9 +58,6 @@ enum QueryModifier { /// Use a separate query provider for local and extern crates SeparateProvideExtern(Ident), - - /// Always remap the ParamEnv's constness before hashing and passing to the query provider - RemapEnvConstness(Ident), } impl Parse for QueryModifier { @@ -126,8 +123,6 @@ impl Parse for QueryModifier { Ok(QueryModifier::EvalAlways(modifier)) } else if modifier == "separate_provide_extern" { Ok(QueryModifier::SeparateProvideExtern(modifier)) - } else if modifier == "remap_env_constness" { - Ok(QueryModifier::RemapEnvConstness(modifier)) } else { Err(Error::new(modifier.span(), "unknown query modifier")) } @@ -227,9 +222,6 @@ struct QueryModifiers { /// Use a separate query provider for local and extern crates separate_provide_extern: Option, - - /// Always remap the ParamEnv's constness before hashing. - remap_env_constness: Option, } /// Process query modifiers into a struct, erroring on duplicates @@ -244,7 +236,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { let mut anon = None; let mut eval_always = None; let mut separate_provide_extern = None; - let mut remap_env_constness = None; for modifier in query.modifiers.0.drain(..) { match modifier { QueryModifier::LoadCached(tcx, id, block) => { @@ -344,12 +335,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { } separate_provide_extern = Some(ident); } - QueryModifier::RemapEnvConstness(ident) => { - if remap_env_constness.is_some() { - panic!("duplicate modifier `remap_env_constness` for query `{}`", query.name); - } - remap_env_constness = Some(ident) - } } } let desc = desc.unwrap_or_else(|| { @@ -366,7 +351,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { anon, eval_always, separate_provide_extern, - remap_env_constness, } } @@ -503,10 +487,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { if let Some(separate_provide_extern) = &modifiers.separate_provide_extern { attributes.push(quote! { (#separate_provide_extern) }); } - // Pass on the remap_env_constness modifier - if let Some(remap_env_constness) = &modifiers.remap_env_constness { - attributes.push(quote! { (#remap_env_constness) }); - } // This uses the span of the query definition for the commas, // which can be important if we later encounter any ambiguity diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index c6fe3e721032f..f090588061844 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -252,14 +252,6 @@ impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> { } } -impl<'tcx, R> Canonical<'tcx, ty::ParamEnvAnd<'tcx, R>> { - #[inline] - pub fn without_const(mut self) -> Self { - self.value = self.value.without_const(); - self - } -} - impl<'tcx, V> Canonical<'tcx, V> { /// Allows you to map the `value` of a canonical while keeping the /// same set of bound variables. @@ -339,6 +331,7 @@ impl<'tcx> CanonicalVarValues<'tcx> { kind: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)), }) .into(), + GenericArgKind::Constness(_) => *kind, }) .collect(), } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 786927e2dad70..07fb341cd5612 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -103,7 +103,6 @@ impl<'tcx> TyCtxt<'tcx> { cid: GlobalId<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { - let param_env = param_env.with_const(); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. let inputs = self.erase_regions(param_env.and(cid)); @@ -122,8 +121,6 @@ impl<'tcx> TyCtxt<'tcx> { cid: GlobalId<'tcx>, span: Option, ) -> EvalToValTreeResult<'tcx> { - let param_env = param_env.with_const(); - debug!(?param_env); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. let inputs = self.erase_regions(param_env.and(cid)); @@ -164,7 +161,6 @@ impl<'tcx> TyCtxtAt<'tcx> { gid: GlobalId<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Result, ErrorHandled> { - let param_env = param_env.with_const(); trace!("eval_to_allocation: Need to compute {:?}", gid); let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?; Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory()) @@ -184,8 +180,7 @@ impl<'tcx> TyCtxtEnsure<'tcx> { let substs = InternalSubsts::identity_for_item(self.tcx, def_id); let instance = ty::Instance::new(def_id, substs); let cid = GlobalId { instance, promoted: None }; - let param_env = - self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const(); + let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. let inputs = self.tcx.erase_regions(param_env.and(cid)); @@ -198,7 +193,7 @@ impl<'tcx> TyCtxtEnsure<'tcx> { assert!(self.tcx.is_static(def_id)); let instance = ty::Instance::mono(self.tcx, def_id); let gid = GlobalId { instance, promoted: None }; - let param_env = ty::ParamEnv::reveal_all().with_const(); + let param_env = ty::ParamEnv::reveal_all(); trace!("eval_to_allocation: Need to compute {:?}", gid); self.eval_to_allocation_raw(param_env.and(gid)) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cbc45526e89fb..4645d12d1fd46 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -995,7 +995,14 @@ rustc_queries! { /// and its field values. query try_destructure_mir_constant(key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>) -> Option> { desc { "destructuring mir constant"} - remap_env_constness + } + + /// Dereference a constant reference or raw pointer and turn the result into a constant + /// again. + query deref_const( + key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>> + ) -> ty::Const<'tcx> { + desc { "deref constant" } } /// Dereference a constant reference or raw pointer and turn the result into a constant @@ -1004,7 +1011,6 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> ) -> mir::ConstantKind<'tcx> { desc { "dereferencing mir constant" } - remap_env_constness } query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { @@ -1240,32 +1246,26 @@ rustc_queries! { /// `ty.is_copy()`, etc, since that will prune the environment where possible. query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Copy`", env.value } - remap_env_constness } /// Query backing `Ty::is_sized`. query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Sized`", env.value } - remap_env_constness } /// Query backing `Ty::is_freeze`. query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } - remap_env_constness } /// Query backing `Ty::is_unpin`. query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Unpin`", env.value } - remap_env_constness } /// Query backing `Ty::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } - remap_env_constness } /// Query backing `Ty::has_significant_drop_raw`. query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` has a significant drop", env.value } - remap_env_constness } /// Query backing `Ty::is_structural_eq_shallow`. @@ -1304,7 +1304,6 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> Result, ty::layout::LayoutError<'tcx>> { desc { "computing layout of `{}`", key.value } - remap_env_constness } /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. @@ -1315,7 +1314,6 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}` function pointers", key.value.0 } - remap_env_constness } /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for @@ -1327,7 +1325,6 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}`", key.value.0 } - remap_env_constness } query dylib_dependency_formats(_: CrateNum) @@ -1607,7 +1604,6 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> ty::inhabitedness::DefIdForest<'tcx> { desc { "computing the inhabitedness of `{:?}`", key } - remap_env_constness } query dep_kind(_: CrateNum) -> CrateDepKind { @@ -1803,7 +1799,6 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } - remap_env_constness } /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. @@ -1811,7 +1806,6 @@ rustc_queries! { goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } - remap_env_constness } /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. @@ -1819,7 +1813,6 @@ rustc_queries! { goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } - remap_env_constness } query implied_outlives_bounds( @@ -1829,7 +1822,6 @@ rustc_queries! { NoSolution, > { desc { "computing implied outlives bounds for `{:?}`", goal } - remap_env_constness } /// Do not call this query directly: @@ -1841,7 +1833,6 @@ rustc_queries! { NoSolution, > { desc { "computing dropck types for `{:?}`", goal } - remap_env_constness } /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or @@ -1869,7 +1860,6 @@ rustc_queries! { NoSolution, > { desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal } - remap_env_constness } /// Do not call this query directly: part of the `Eq` type-op @@ -1880,7 +1870,6 @@ rustc_queries! { NoSolution, > { desc { "evaluating `type_op_eq` `{:?}`", goal } - remap_env_constness } /// Do not call this query directly: part of the `Subtype` type-op @@ -1891,7 +1880,6 @@ rustc_queries! { NoSolution, > { desc { "evaluating `type_op_subtype` `{:?}`", goal } - remap_env_constness } /// Do not call this query directly: part of the `ProvePredicate` type-op @@ -1912,7 +1900,6 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } - remap_env_constness } /// Do not call this query directly: part of the `Normalize` type-op @@ -1923,7 +1910,6 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } - remap_env_constness } /// Do not call this query directly: part of the `Normalize` type-op @@ -1934,7 +1920,6 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } - remap_env_constness } /// Do not call this query directly: part of the `Normalize` type-op @@ -1945,7 +1930,6 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } - remap_env_constness } query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool { @@ -1959,7 +1943,6 @@ rustc_queries! { goal: CanonicalTyGoal<'tcx> ) -> MethodAutoderefStepsResult<'tcx> { desc { "computing autoderef types for `{:?}`", goal } - remap_env_constness } query supported_target_features(_: CrateNum) -> FxHashMap> { @@ -1992,7 +1975,6 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)> ) -> Result>, ErrorGuaranteed> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } - remap_env_constness } query resolve_instance_of_const_arg( @@ -2002,7 +1984,6 @@ rustc_queries! { "resolving instance of the const argument `{}`", ty::Instance::new(key.value.0.to_def_id(), key.value.2), } - remap_env_constness } query normalize_opaque_types(key: &'tcx ty::List>) -> &'tcx ty::List> { @@ -2017,7 +1998,6 @@ rustc_queries! { /// size, to account for partial initialisation. See #49298 for details.) query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "conservatively checking if {:?} is privately uninhabited", key } - remap_env_constness } query limits(key: ()) -> Limits { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index fe7f72024d358..0b128fbfe3e45 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -616,7 +616,7 @@ pub enum ImplSource<'tcx, N> { /// for some type parameter. The `Vec` represents the /// obligations incurred from normalizing the where-clause (if /// any). - Param(Vec, ty::BoundConstness), + Param(Vec, ty::ConstnessArg), /// Virtual calls through an object. Object(ImplSourceObjectData<'tcx, N>), diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index e6aab30a150de..2bc34ead8ba6e 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -121,4 +121,18 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { { Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) } + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + match (a, b) { + (_, ty::ConstnessArg::Infer) => return Ok(a), + (ty::ConstnessArg::Infer, _) => { + return Err(TypeError::ConstnessArgMismatch(relate::expected_found(self, a, b))); + } + _ => relate::super_relate_constness(self, a, b), + } + } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a594dab2e20a3..5d9d6f8df3fc4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -921,6 +921,8 @@ impl<'tcx> CanonicalUserType<'tcx> { } _ => false, }, + + GenericArgKind::Constness(_) => false, } }) } @@ -1822,7 +1824,7 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable // This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} -CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } } +CloneLiftImpls! { for<'tcx> { ty::ConstnessArg, Constness, traits::WellFormedLoc, } } pub mod tls { use super::{ptr_eq, GlobalCtxt, TyCtxt}; @@ -2436,7 +2438,9 @@ impl<'tcx> TyCtxt<'tcx> { let adt_def = self.adt_def(wrapper_def_id); let substs = InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(), + GenericParamDefKind::Lifetime + | GenericParamDefKind::Const { .. } + | GenericParamDefKind::Constness => bug!(), GenericParamDefKind::Type { has_default, .. } => { if param.index == 0 { ty_param.into() @@ -2625,6 +2629,7 @@ impl<'tcx> TyCtxt<'tcx> { GenericParamDefKind::Const { .. } => { self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into() } + GenericParamDefKind::Constness => ty::ConstnessArg::Not.into(), // TODO sus } } @@ -2959,6 +2964,15 @@ impl<'tcx> TyCtxt<'tcx> { }) ) } + + pub fn should_have_constness(self, def_id: DefId) -> bool { + match self.def_kind(def_id) { + DefKind::Trait => true, + DefKind::Impl if self.constness(def_id) == hir::Constness::Const => true, + DefKind::AssocFn => self.should_have_constness(self.parent(def_id)), + _ => false, + } + } } impl<'tcx> TyCtxtAt<'tcx> { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 49a518b101dd1..96e6ae4349c16 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -34,6 +34,7 @@ impl ExpectedFound { pub enum TypeError<'tcx> { Mismatch, ConstnessMismatch(ExpectedFound), + ConstnessArgMismatch(ExpectedFound), PolarityMismatch(ExpectedFound), UnsafetyMismatch(ExpectedFound), AbiMismatch(ExpectedFound), @@ -103,6 +104,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { CyclicTy(_) => write!(f, "cyclic type of infinite size"), CyclicConst(_) => write!(f, "encountered a self-referencing constant"), Mismatch => write!(f, "types differ"), + ConstnessArgMismatch(_) => write!(f, "constness arguments differ"), ConstnessMismatch(values) => { write!(f, "expected {} bound, found {} bound", values.expected, values.found) } @@ -214,10 +216,21 @@ impl<'tcx> TypeError<'tcx> { pub fn must_include_note(&self) -> bool { use self::TypeError::*; match self { - CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | ConstnessMismatch(_) - | PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_) - | ArgumentSorts(..) | Sorts(_) | IntMismatch(_) | FloatMismatch(_) - | VariadicMismatch(_) | TargetFeatureCast(_) => false, + CyclicTy(_) + | CyclicConst(_) + | UnsafetyMismatch(_) + | ConstnessMismatch(_) + | PolarityMismatch(_) + | Mismatch + | AbiMismatch(_) + | FixedArraySize(_) + | ArgumentSorts(..) + | Sorts(_) + | IntMismatch(_) + | FloatMismatch(_) + | VariadicMismatch(_) + | TargetFeatureCast(_) + | ConstnessArgMismatch(_) => false, Mutability | ArgumentMutability(_) diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 8d019a3bad8cc..310eecca63031 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -221,6 +221,9 @@ impl DeepRejectCtxt { (GenericArgKind::Const(obl), GenericArgKind::Const(imp)) => { self.consts_may_unify(obl, imp) } + (GenericArgKind::Constness(obl), GenericArgKind::Constness(imp)) => { + self.constness_may_unify(obl, imp) + } _ => bug!("kind mismatch: {obligation_arg} {impl_arg}"), } } @@ -402,4 +405,16 @@ impl DeepRejectCtxt { } } } + + pub fn constness_may_unify( + self, + obligation_ct: ty::ConstnessArg, + impl_ct: ty::ConstnessArg, + ) -> bool { + match (obligation_ct, impl_ct) { + (_, ty::ConstnessArg::Const) => true, + (ty::ConstnessArg::Infer, _) => true, + _ => obligation_ct == impl_ct, + } + } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index ea6bb8a7abd4b..ddd13fbfc3a4f 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -336,6 +336,8 @@ impl FlagComputation { GenericArgKind::Type(ty) => self.add_ty(ty), GenericArgKind::Lifetime(lt) => self.add_region(lt), GenericArgKind::Const(ct) => self.add_const(ct), + // TODO ? + GenericArgKind::Constness(_) => {} } } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index f8893ae29f58e..624e45b8fb928 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -131,6 +131,10 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> { uv.super_fold_with(self) } + fn fold_constness(&mut self, c: ty::ConstnessArg) -> ty::ConstnessArg { + c.super_fold_with(self) + } + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { p.super_fold_with(self) } @@ -178,6 +182,10 @@ pub trait FallibleTypeFolder<'tcx>: Sized { c.try_super_fold_with(self) } + fn try_fold_constness(&mut self, c: ty::ConstnessArg) -> Result { + c.try_super_fold_with(self) + } + fn try_fold_predicate( &mut self, p: ty::Predicate<'tcx>, @@ -224,6 +232,10 @@ where Ok(self.fold_const(c)) } + fn try_fold_constness(&mut self, c: ty::ConstnessArg) -> Result { + Ok(self.fold_constness(c)) + } + fn try_fold_unevaluated( &mut self, c: ty::Unevaluated<'tcx>, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index add2df25884e3..b102f3ab076cb 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -15,6 +15,7 @@ pub enum GenericParamDefKind { Lifetime, Type { has_default: bool, object_lifetime_default: ObjectLifetimeDefault, synthetic: bool }, Const { has_default: bool }, + Constness, } impl GenericParamDefKind { @@ -23,6 +24,7 @@ impl GenericParamDefKind { GenericParamDefKind::Lifetime => "lifetime", GenericParamDefKind::Type { .. } => "type", GenericParamDefKind::Const { .. } => "constant", + GenericParamDefKind::Constness => "constness", } } pub fn to_ord(&self) -> ast::ParamKindOrd { @@ -30,12 +32,13 @@ impl GenericParamDefKind { GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, GenericParamDefKind::Const { .. } => ast::ParamKindOrd::Const, + GenericParamDefKind::Constness => ast::ParamKindOrd::Infer, } } pub fn is_ty_or_const(&self) -> bool { match self { - GenericParamDefKind::Lifetime => false, + GenericParamDefKind::Lifetime | GenericParamDefKind::Constness => false, GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => true, } } @@ -75,7 +78,7 @@ impl GenericParamDef { match self.kind { GenericParamDefKind::Type { has_default, .. } | GenericParamDefKind::Const { has_default } => has_default, - GenericParamDefKind::Lifetime => false, + GenericParamDefKind::Lifetime | GenericParamDefKind::Constness => false, } } @@ -100,13 +103,14 @@ pub struct GenericParamCount { pub lifetimes: usize, pub types: usize, pub consts: usize, + pub has_constness: bool, } /// Information about the formal type/lifetime parameters associated /// with an item or method. Analogous to `hir::Generics`. /// /// The ordering of parameters is the same as in `Subst` (excluding child generics): -/// `Self` (optionally), `Lifetime` params..., `Type` params... +/// `Self` (optionally), `Lifetime` params..., `Type` params..., `constness` (optional) #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub struct Generics { pub parent: Option, @@ -118,6 +122,8 @@ pub struct Generics { pub param_def_id_to_index: FxHashMap, pub has_self: bool, + pub has_constness: bool, + pub parent_has_constness: bool, pub has_late_bound_regions: Option, } @@ -138,6 +144,12 @@ impl<'tcx> Generics { GenericParamDefKind::Lifetime => own_counts.lifetimes += 1, GenericParamDefKind::Type { .. } => own_counts.types += 1, GenericParamDefKind::Const { .. } => own_counts.consts += 1, + GenericParamDefKind::Constness => { + if own_counts.has_constness { + bug!("more than one constness parameter"); + } + own_counts.has_constness = true; + } } } @@ -149,7 +161,7 @@ impl<'tcx> Generics { for param in &self.params { match param.kind { - GenericParamDefKind::Lifetime => (), + GenericParamDefKind::Lifetime | GenericParamDefKind::Constness => (), GenericParamDefKind::Type { has_default, .. } => { own_defaults.types += has_default as usize; } @@ -181,7 +193,7 @@ impl<'tcx> Generics { GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { return true; } - GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Lifetime | GenericParamDefKind::Constness => {} } } false @@ -228,6 +240,12 @@ impl<'tcx> Generics { } } + /// Returns the `ConstnessArg` + // TODO just use self.has_constness? + pub fn has_constness_param(&'tcx self) -> bool { + self.params.iter().any(|param| matches!(param.kind, ty::GenericParamDefKind::Constness)) + } + /// Returns `true` if `params` has `impl Trait`. pub fn has_impl_trait(&'tcx self) -> bool { self.params.iter().any(|param| { @@ -279,6 +297,15 @@ impl<'tcx> Generics { let own = &substs[self.parent_count..][..self.params.len()]; if self.has_self && self.parent.is_none() { &own[1..] } else { &own } } + + /*pub fn expected_arg_count(&self) -> std::ops::RangeInclusive { + self.count() + todo!() + }*/ + + pub fn expected_parent_count(&self) -> std::ops::RangeInclusive { + self.parent_count..=self.parent_count + self.parent_has_constness as usize + } } /// Bounds on generics. diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index 88397a2bb56ba..43db77b03339d 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -97,6 +97,10 @@ impl<'a, 'tcx> HashStable> for ty::subst::GenericArgKin 0xF5u8.hash_stable(hcx, hasher); lt.hash_stable(hcx, hasher); } + ty::subst::GenericArgKind::Constness(constness) => { + 0xFFu8.hash_stable(hcx, hasher); + constness.hash_stable(hcx, hasher); + } } } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 391abdbe84c5a..2c257c330a4ec 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -323,6 +323,7 @@ impl<'tcx> Instance<'tcx> { ty::GenericParamDefKind::Const { .. } => { bug!("Instance::mono: {:?} has const parameters", def_id) } + ty::GenericParamDefKind::Constness => ty::ConstnessArg::Not.into(), }); Instance::new(def_id, substs) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c2c7b3df844ad..f9d38260d1100 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -297,6 +297,36 @@ impl fmt::Display for BoundConstness { } } +/// Whether we should select const impls only or not, or whether this is variable. +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + HashStable, + TyEncodable, + TyDecodable, + PartialOrd, + Ord +)] +pub enum ConstnessArg { + Const, + Not, + Infer, +} + +impl fmt::Display for ConstnessArg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Self::Not => "(constness: not)", + Self::Const => "(constness: const)", + Self::Infer => "(constness: infer)", + }) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)] #[derive(TypeFoldable, TypeVisitable)] pub struct ClosureSizeProfileData<'tcx> { @@ -309,7 +339,6 @@ pub struct ClosureSizeProfileData<'tcx> { pub trait DefIdTree: Copy { fn opt_parent(self, id: DefId) -> Option; - #[inline] #[track_caller] fn parent(self, id: DefId) -> DefId { match self.opt_parent(id) { @@ -560,10 +589,9 @@ impl<'tcx> Predicate<'tcx> { let kind = self .kind() .map_bound(|kind| match kind { - PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) => { + PredicateKind::Trait(TraitPredicate { trait_ref, polarity }) => { Some(PredicateKind::Trait(TraitPredicate { trait_ref, - constness, polarity: polarity.flip()?, })) } @@ -774,8 +802,6 @@ impl<'tcx> Predicate<'tcx> { pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, - pub constness: BoundConstness, - /// If polarity is Positive: we are proving that the trait is implemented. /// /// If polarity is Negative: we are proving that a negative impl of this trait @@ -789,27 +815,6 @@ pub struct TraitPredicate<'tcx> { pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; impl<'tcx> TraitPredicate<'tcx> { - pub fn remap_constness(&mut self, tcx: TyCtxt<'tcx>, param_env: &mut ParamEnv<'tcx>) { - if std::intrinsics::unlikely(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) { - // remap without changing constness of this predicate. - // this is because `T: ~const Drop` has a different meaning to `T: Drop` - // FIXME(fee1-dead): remove this logic after beta bump - param_env.remap_constness_with(self.constness) - } else { - *param_env = param_env.with_constness(self.constness.and(param_env.constness())) - } - } - - /// Remap the constness of this predicate before emitting it for diagnostics. - pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { - // this is different to `remap_constness` that callees want to print this predicate - // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the - // param_env is not const because we it is always satisfied in non-const contexts. - if let hir::Constness::NotConst = param_env.constness() { - self.constness = ty::BoundConstness::NotConst; - } - } - pub fn def_id(self) -> DefId { self.trait_ref.def_id } @@ -818,9 +823,13 @@ impl<'tcx> TraitPredicate<'tcx> { self.trait_ref.self_ty() } - #[inline] - pub fn is_const_if_const(self) -> bool { - self.constness == BoundConstness::ConstIfConst + pub fn constness(self) -> ty::ConstnessArg { + self.trait_ref.constness() + } + + pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { + self.trait_ref = self.trait_ref.without_const(tcx); + self } } @@ -834,17 +843,9 @@ impl<'tcx> PolyTraitPredicate<'tcx> { self.map_bound(|trait_ref| trait_ref.self_ty()) } - /// Remap the constness of this predicate before emitting it for diagnostics. - pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { - *self = self.map_bound(|mut p| { - p.remap_constness_diag(param_env); - p - }); - } - - #[inline] - pub fn is_const_if_const(self) -> bool { - self.skip_binder().is_const_if_const() + pub fn constness(self) -> ty::ConstnessArg { + // TODO remove panic + self.skip_binder().constness() } } @@ -989,6 +990,12 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { } } +impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.to_poly_trait_predicate().to_predicate(tcx) + } +} + impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(PredicateKind::Trait).to_predicate(tcx) @@ -1331,27 +1338,22 @@ pub struct ParamEnv<'tcx> { #[derive(Copy, Clone)] struct ParamTag { reveal: traits::Reveal, - constness: hir::Constness, } unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag { - const BITS: usize = 2; + const BITS: usize = 1; #[inline] fn into_usize(self) -> usize { match self { - Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0, - Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1, - Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2, - Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3, + Self { reveal: traits::Reveal::UserFacing } => 0, + Self { reveal: traits::Reveal::All } => 1, } } #[inline] unsafe fn from_usize(ptr: usize) -> Self { match ptr { - 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, - 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, - 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, - 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const }, + 0 => Self { reveal: traits::Reveal::UserFacing }, + 1 => Self { reveal: traits::Reveal::All }, _ => std::hint::unreachable_unchecked(), } } @@ -1362,7 +1364,6 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> { f.debug_struct("ParamEnv") .field("caller_bounds", &self.caller_bounds()) .field("reveal", &self.reveal()) - .field("constness", &self.constness()) .finish() } } @@ -1371,7 +1372,6 @@ impl<'a, 'tcx> HashStable> for ParamEnv<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.caller_bounds().hash_stable(hcx, hasher); self.reveal().hash_stable(hcx, hasher); - self.constness().hash_stable(hcx, hasher); } } @@ -1383,7 +1383,6 @@ impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { Ok(ParamEnv::new( self.caller_bounds().try_fold_with(folder)?, self.reveal().try_fold_with(folder)?, - self.constness().try_fold_with(folder)?, )) } } @@ -1391,8 +1390,7 @@ impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { impl<'tcx> TypeVisitable<'tcx> for ParamEnv<'tcx> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.caller_bounds().visit_with(visitor)?; - self.reveal().visit_with(visitor)?; - self.constness().visit_with(visitor) + self.reveal().visit_with(visitor) } } @@ -1403,7 +1401,7 @@ impl<'tcx> ParamEnv<'tcx> { /// type-checking. #[inline] pub fn empty() -> Self { - Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst) + Self::new(List::empty(), Reveal::UserFacing) } #[inline] @@ -1416,16 +1414,6 @@ impl<'tcx> ParamEnv<'tcx> { self.packed.tag().reveal } - #[inline] - pub fn constness(self) -> hir::Constness { - self.packed.tag().constness - } - - #[inline] - pub fn is_const(self) -> bool { - self.packed.tag().constness == hir::Constness::Const - } - /// Construct a trait environment with no where-clauses in scope /// where the values of all `impl Trait` and other hidden types /// are revealed. This is suitable for monomorphized, post-typeck @@ -1435,17 +1423,13 @@ impl<'tcx> ParamEnv<'tcx> { /// or invoke `param_env.with_reveal_all()`. #[inline] pub fn reveal_all() -> Self { - Self::new(List::empty(), Reveal::All, hir::Constness::NotConst) + Self::new(List::empty(), Reveal::All) } /// Construct a trait environment with the given set of predicates. #[inline] - pub fn new( - caller_bounds: &'tcx List>, - reveal: Reveal, - constness: hir::Constness, - ) -> Self { - ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) } + pub fn new(caller_bounds: &'tcx List>, reveal: Reveal) -> Self { + ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) } } pub fn with_user_facing(mut self) -> Self { @@ -1453,29 +1437,6 @@ impl<'tcx> ParamEnv<'tcx> { self } - #[inline] - pub fn with_constness(mut self, constness: hir::Constness) -> Self { - self.packed.set_tag(ParamTag { constness, ..self.packed.tag() }); - self - } - - #[inline] - pub fn with_const(mut self) -> Self { - self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() }); - self - } - - #[inline] - pub fn without_const(mut self) -> Self { - self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() }); - self - } - - #[inline] - pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) { - *self = self.with_constness(constness.and(self.constness())) - } - /// Returns a new parameter environment with the same clauses, but /// which "reveals" the true results of projections in all cases /// (even for associated types that are specializable). This is @@ -1490,17 +1451,13 @@ impl<'tcx> ParamEnv<'tcx> { return self; } - ParamEnv::new( - tcx.normalize_opaque_types(self.caller_bounds()), - Reveal::All, - self.constness(), - ) + ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All) } /// Returns this same environment but with no caller bounds. #[inline] pub fn without_caller_bounds(self) -> Self { - Self::new(List::empty(), self.reveal(), self.constness()) + Self::new(List::empty(), self.reveal()) } /// Creates a suitable environment in which to perform trait @@ -1530,24 +1487,6 @@ impl<'tcx> ParamEnv<'tcx> { } } -// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that -// the constness of trait bounds is being propagated correctly. -impl<'tcx> PolyTraitRef<'tcx> { - #[inline] - pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| ty::TraitPredicate { - trait_ref, - constness, - polarity: ty::ImplPolarity::Positive, - }) - } - - #[inline] - pub fn without_const(self) -> PolyTraitPredicate<'tcx> { - self.with_constness(BoundConstness::NotConst) - } -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, @@ -1558,12 +1497,6 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> { pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { (self.param_env, self.value) } - - #[inline] - pub fn without_const(mut self) -> Self { - self.param_env = self.param_env.without_const(); - self - } } impl<'a, 'tcx, T> HashStable> for ParamEnvAnd<'tcx, T> diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f721a175c9834..3e66355ba3c93 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1824,12 +1824,17 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { GenericArgKind::Lifetime(r) => !r.is_erased(), _ => false, }); - let args = args.iter().cloned().filter(|arg| match arg.unpack() { - GenericArgKind::Lifetime(_) => print_regions, - _ => true, - }); + let mut args = args + .iter() + .cloned() + .filter(|arg| match arg.unpack() { + GenericArgKind::Lifetime(_) => print_regions, + GenericArgKind::Constness(_) => false, + _ => true, + }) + .peekable(); - if args.clone().next().is_some() { + if args.peek().is_some() { if self.in_value { write!(self, "::")?; } @@ -2381,6 +2386,8 @@ macro_rules! define_print_and_forward_display { }; } +// TODO fix printing + /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// the trait path. That is, it will print `Trait` instead of /// `>`. @@ -2517,6 +2524,13 @@ define_print_and_forward_display! { } TraitRefPrintOnlyTraitPath<'tcx> { + if cx.tcx().sess.verbose() { + match self.0.constness() { + ty::ConstnessArg::Not => {}, + ty::ConstnessArg::Const => p!(write("~const ")), + ty::ConstnessArg::Infer => p!(write("_const ")), // TODO wonky + } + } p!(print_def_path(self.0.def_id, self.0.substs)); } @@ -2525,10 +2539,6 @@ define_print_and_forward_display! { } TraitPredPrintModifiersAndPath<'tcx> { - if let ty::BoundConstness::ConstIfConst = self.0.constness { - p!("~const ") - } - if let ty::ImplPolarity::Negative = self.0.polarity { p!("!") } @@ -2554,9 +2564,6 @@ define_print_and_forward_display! { ty::TraitPredicate<'tcx> { p!(print(self.trait_ref.self_ty()), ": "); - if let ty::BoundConstness::ConstIfConst = self.constness { - p!("~const "); - } p!(print(self.trait_ref.print_only_trait_path())) } @@ -2624,6 +2631,7 @@ define_print_and_forward_display! { GenericArgKind::Lifetime(lt) => p!(print(lt)), GenericArgKind::Type(ty) => p!(print(ty)), GenericArgKind::Const(ct) => p!(print(ct)), + GenericArgKind::Constness(ca) => p!("{ca:?}"), } } } diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 3d662ed5de4ba..5f84ef9e075ab 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -161,16 +161,6 @@ macro_rules! separate_provide_extern_default { }; } -macro_rules! opt_remap_env_constness { - ([][$name:ident]) => {}; - ([(remap_env_constness) $($rest:tt)*][$name:ident]) => { - let $name = $name.without_const(); - }; - ([$other:tt $($modifiers:tt)*][$name:ident]) => { - opt_remap_env_constness!([$($modifiers)*][$name]) - }; -} - macro_rules! define_callbacks { (<$tcx:tt> $($(#[$attr:meta])* @@ -217,7 +207,6 @@ macro_rules! define_callbacks { #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) { let key = key.into_query_param(); - opt_remap_env_constness!([$($modifiers)*][key]); let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop); @@ -246,7 +235,6 @@ macro_rules! define_callbacks { pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx> { let key = key.into_query_param(); - opt_remap_env_constness!([$($modifiers)*][key]); let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy); diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 818affa7113a1..01aaa17f28b91 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -99,6 +99,12 @@ pub trait TypeRelation<'tcx>: Sized { ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>; + + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg>; } pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy { @@ -141,7 +147,11 @@ pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>( b_subst: SubstsRef<'tcx>, ) -> RelateResult<'tcx, SubstsRef<'tcx>> { relation.tcx().mk_substs(iter::zip(a_subst, b_subst).map(|(a, b)| { - relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b) + if let GenericArgKind::Constness(_) = a.unpack() && let GenericArgKind::Constness(_) = b.unpack() { + relation.relate(a, b) + } else { + relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b) + } })) } @@ -226,6 +236,16 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { } } +impl<'tcx> Relate<'tcx> for ty::ConstnessArg { + fn relate>( + relation: &mut R, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + relation.constness_args(a, b) + } +} + impl<'tcx> Relate<'tcx> for ty::BoundConstness { fn relate>( relation: &mut R, @@ -646,6 +666,20 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } +pub fn super_relate_constness<'tcx, R: TypeRelation<'tcx>>( + relation: &mut R, + a: ty::ConstnessArg, + b: ty::ConstnessArg, +) -> RelateResult<'tcx, ty::ConstnessArg> { + match (a, b) { + (ty::ConstnessArg::Infer, _) | (_, ty::ConstnessArg::Infer) => { + bug!("var types encountered in super_relate_contness: {a:?} {b:?}"); + } + (a, b) if a == b => Ok(a), + _ => Err(TypeError::ConstnessArgMismatch(expected_found(relation, a, b))), + } +} + impl<'tcx> Relate<'tcx> for &'tcx ty::List>> { fn relate>( relation: &mut R, @@ -762,6 +796,9 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { (GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => { Ok(relation.relate(a_ct, b_ct)?.into()) } + (GenericArgKind::Constness(a_ca), GenericArgKind::Constness(b_ca)) => { + Ok(relation.relate(a_ca, b_ca)?.into()) + } (GenericArgKind::Lifetime(unpacked), x) => { bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) } @@ -771,6 +808,9 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { (GenericArgKind::Const(unpacked), x) => { bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) } + (GenericArgKind::Constness(unpacked), x) => { + bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) + } } } } @@ -797,7 +837,6 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> { Ok(ty::TraitPredicate { trait_ref: relation.relate(a.trait_ref, b.trait_ref)?, - constness: relation.relate(a.constness, b.constness)?, polarity: relation.relate(a.polarity, b.polarity)?, }) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 391a0a20c9662..625c29d8a285d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -132,9 +132,6 @@ impl fmt::Debug for ty::ParamConst { impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let ty::BoundConstness::ConstIfConst = self.constness { - write!(f, "~const ")?; - } write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity) } } @@ -353,11 +350,8 @@ impl<'a, 'tcx> Lift<'tcx> for Term<'a> { impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> { type Lifted = ty::TraitPredicate<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option> { - tcx.lift(self.trait_ref).map(|trait_ref| ty::TraitPredicate { - trait_ref, - constness: self.constness, - polarity: self.polarity, - }) + tcx.lift(self.trait_ref) + .map(|trait_ref| ty::TraitPredicate { trait_ref, polarity: self.polarity }) } } @@ -468,7 +462,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { type Lifted = ty::ParamEnv<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { tcx.lift(self.caller_bounds()) - .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal(), self.constness())) + .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal())) } } @@ -581,6 +575,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { Some(match self { Mismatch => Mismatch, + ConstnessArgMismatch(x) => ConstnessArgMismatch(x), ConstnessMismatch(x) => ConstnessMismatch(x), PolarityMismatch(x) => PolarityMismatch(x), UnsafetyMismatch(x) => UnsafetyMismatch(x), @@ -1111,6 +1106,33 @@ impl<'tcx> TypeSuperVisitable<'tcx> for ty::Region<'tcx> { } } +impl<'tcx> TypeFoldable<'tcx> for ty::ConstnessArg { + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_constness(self) + } +} + +impl<'tcx> TypeSuperFoldable<'tcx> for ty::ConstnessArg { + fn try_super_fold_with>( + self, + _folder: &mut F, + ) -> Result { + Ok(self) + } +} + +impl<'tcx> TypeVisitable<'tcx> for ty::ConstnessArg { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_constness_arg(*self) + } +} + +impl<'tcx> TypeSuperVisitable<'tcx> for ty::ConstnessArg { + fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow { + ControlFlow::CONTINUE + } +} + impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { fn try_fold_with>(self, folder: &mut F) -> Result { folder.try_fold_predicate(self) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d663f1a3ec6e7..8431500135c9d 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -32,6 +32,8 @@ use rustc_type_ir::sty::TyKind::*; use rustc_type_ir::RegionKind as IrRegionKind; use rustc_type_ir::TyKind as IrTyKind; +use super::GenericArgKind; + // Re-export the `TyKind` from `rustc_type_ir` here for convenience #[rustc_diagnostic_item = "TyKind"] pub type TyKind<'tcx> = IrTyKind>; @@ -691,7 +693,7 @@ impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { use crate::ty::ToPredicate; match self.skip_binder() { ExistentialPredicate::Trait(tr) => { - self.rebind(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx) + self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) } ExistentialPredicate::Projection(p) => { self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) @@ -701,7 +703,7 @@ impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]), }); - trait_ref.without_const().to_predicate(tcx) + trait_ref.to_predicate(tcx) } } } @@ -814,6 +816,54 @@ impl<'tcx> TraitRef<'tcx> { let defs = tcx.generics_of(trait_id); ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) } } + + // TODO remove this hack! + pub fn normalize_constness_equate(&self, tcx: TyCtxt<'tcx>, actual: &mut SubstsRef<'tcx>) { + if self.constness() == ty::ConstnessArg::Not { + *actual = tcx.mk_substs(actual.iter().filter(|arg| match arg.unpack() { + ty::subst::GenericArgKind::Constness(_) => false, + _ => true, + })); + } + } + + pub fn constness(self) -> ty::ConstnessArg { + for arg in self.substs.iter() { + match arg.unpack() { + ty::subst::GenericArgKind::Constness(constness) => return constness, + _ => {} + } + } + ty::ConstnessArg::Not + } + + pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { + if self.constness() != ty::ConstnessArg::Not { + self.substs = tcx.mk_substs(self.substs.iter().map(|arg| match arg.unpack() { + ty::subst::GenericArgKind::Constness(_) => ty::ConstnessArg::Not.into(), + _ => arg, + })); + } + + self + } + + pub fn with_const(mut self, tcx: TyCtxt<'tcx>) -> Self { + if self.constness() != ty::ConstnessArg::Const { + self.substs = tcx.mk_substs(self.substs.iter().map(|arg| match arg.unpack() { + GenericArgKind::Constness(_) => ty::ConstnessArg::Const.into(), + _ => arg, + })); + } + + self + } + + pub fn eq_modulo_constness(&self, other: &TraitRef<'tcx>) -> bool { + let f = |s: &GenericArg<'_>| !matches!(s.unpack(), GenericArgKind::Constness(_)); + self.def_id == other.def_id + && self.substs.iter().filter(f).eq(other.substs.iter().filter(f)) + } } pub type PolyTraitRef<'tcx> = Binder<'tcx, TraitRef<'tcx>>; @@ -830,7 +880,6 @@ impl<'tcx> PolyTraitRef<'tcx> { pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { self.map_bound(|trait_ref| ty::TraitPredicate { trait_ref, - constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, }) } @@ -839,10 +888,18 @@ impl<'tcx> PolyTraitRef<'tcx> { pub fn to_poly_trait_predicate_negative_polarity(&self) -> ty::PolyTraitPredicate<'tcx> { self.map_bound(|trait_ref| ty::TraitPredicate { trait_ref, - constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Negative, }) } + + pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Self { + self.map_bound(|tr| tr.without_const(tcx)) + } + + pub fn eq_modulo_constness(&self, other: &Self) -> bool { + self.bound_vars() == other.bound_vars() + && self.skip_binder().eq_modulo_constness(other.as_ref().skip_binder()) + } } /// An existential reference to a trait, where `Self` is erased. diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 3a524d7b0f307..e65740c61ceb8 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -34,19 +34,21 @@ use std::slice; #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct GenericArg<'tcx> { ptr: NonZeroUsize, - marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>, + marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>, ty::ConstnessArg)>, } const TAG_MASK: usize = 0b11; const TYPE_TAG: usize = 0b00; const REGION_TAG: usize = 0b01; const CONST_TAG: usize = 0b10; +const CONSTNESS_TAG: usize = 0b11; #[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord)] pub enum GenericArgKind<'tcx> { Lifetime(ty::Region<'tcx>), Type(Ty<'tcx>), Const(ty::Const<'tcx>), + Constness(ty::ConstnessArg), } /// This function goes from `&'a [Ty<'tcx>]` to `&'a [GenericArg<'tcx>]` @@ -93,6 +95,14 @@ impl<'tcx> GenericArgKind<'tcx> { assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize) } + GenericArgKind::Constness(carg) => ( + CONSTNESS_TAG, + match carg { + ty::ConstnessArg::Not => 0, + ty::ConstnessArg::Const => 0b100, + ty::ConstnessArg::Infer => 0b1000, + }, + ), }; GenericArg { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } @@ -105,6 +115,7 @@ impl<'tcx> fmt::Debug for GenericArg<'tcx> { GenericArgKind::Lifetime(lt) => lt.fmt(f), GenericArgKind::Type(ty) => ty.fmt(f), GenericArgKind::Const(ct) => ct.fmt(f), + GenericArgKind::Constness(ca) => ca.fmt(f), } } } @@ -142,6 +153,13 @@ impl<'tcx> From> for GenericArg<'tcx> { } } +impl<'tcx> From for GenericArg<'tcx> { + #[inline] + fn from(c: ty::ConstnessArg) -> GenericArg<'tcx> { + GenericArgKind::Constness(c).pack() + } +} + impl<'tcx> GenericArg<'tcx> { #[inline] pub fn unpack(self) -> GenericArgKind<'tcx> { @@ -160,6 +178,12 @@ impl<'tcx> GenericArg<'tcx> { CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), ))), + CONSTNESS_TAG => GenericArgKind::Constness(match ptr & (!TAG_MASK) { + 0 => ty::ConstnessArg::Not, + 0b100 => ty::ConstnessArg::Const, + 0b1000 => ty::ConstnessArg::Infer, + _ => intrinsics::unreachable(), + }), _ => intrinsics::unreachable(), } } @@ -192,6 +216,7 @@ impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> { GenericArgKind::Lifetime(lt) => tcx.lift(lt).map(|lt| lt.into()), GenericArgKind::Type(ty) => tcx.lift(ty).map(|ty| ty.into()), GenericArgKind::Const(ct) => tcx.lift(ct).map(|ct| ct.into()), + GenericArgKind::Constness(ca) => Some(ca.into()), } } } @@ -202,6 +227,7 @@ impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> { GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into), GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into), GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), + GenericArgKind::Constness(cn) => cn.try_fold_with(folder).map(Into::into), } } } @@ -212,6 +238,7 @@ impl<'tcx> TypeVisitable<'tcx> for GenericArg<'tcx> { GenericArgKind::Lifetime(lt) => lt.visit_with(visitor), GenericArgKind::Type(ty) => ty.visit_with(visitor), GenericArgKind::Const(ct) => ct.visit_with(visitor), + GenericArgKind::Constness(cn) => cn.visit_with(visitor), } } } @@ -553,8 +580,8 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { _ => { let msg = format!( "Region parameter out of range \ - when substituting in region {} (index={})", - data.name, data.index + when substituting in region {} (index={}, substs={:?})", + data.name, data.index, self.substs ); span_bug!(DUMMY_SP, "{}", msg); } @@ -583,6 +610,23 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { } } + fn fold_constness(&mut self, c: ty::ConstnessArg) -> ty::ConstnessArg { + if let ty::ConstnessArg::Const | ty::ConstnessArg::Infer = c { + let ret = self + .substs + .iter() + .find_map(|param| match param.unpack() { + GenericArgKind::Constness(c) => Some(c), + _ => None, + }) + .unwrap_or(ty::ConstnessArg::Not); // <- since there is no constness in subst, it must be non-const + trace!(?c, ?ret); + ret + } else { + c.super_fold_with(self) + } + } + #[inline] fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { c.super_fold_with(self) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 4d2f69b23fa09..09d70d0b01acf 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -458,6 +458,7 @@ impl<'tcx> TyCtxt<'tcx> { // Error: not a const param _ => false, }, + GenericArgKind::Constness(_) => false, } }) .map(|(item_param, _)| item_param) @@ -501,6 +502,7 @@ impl<'tcx> TyCtxt<'tcx> { } _ => return Err(NotUniqueParam::NotParam(c.into())), }, + GenericArgKind::Constness(_) => {} } } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 5365067209af9..9b2bf3d353de9 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -210,6 +210,10 @@ pub trait TypeVisitor<'tcx>: Sized { fn visit_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> ControlFlow { c.super_visit_with(self) } + + fn visit_constness_arg(&mut self, c: ty::ConstnessArg) -> ControlFlow { + c.super_visit_with(self) + } } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 02fe1f3a7bded..6b39e7fb51beb 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -203,5 +203,6 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) } } } + GenericArgKind::Constness(_) => {} } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index e32e0b11ba497..bf0d459e26fb4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -250,6 +250,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { ty::subst::GenericArgKind::Lifetime(_) => false, ty::subst::GenericArgKind::Type(t) => t.is_fn_ptr(), ty::subst::GenericArgKind::Const(_) => false, + ty::subst::GenericArgKind::Constness(_) => false, }) } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b3ac0f4cbeaa4..a7dc821b879d1 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -629,7 +629,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { .flat_map(|arg| arg.walk()) .filter(|arg| match arg.unpack() { GenericArgKind::Type(_) | GenericArgKind::Const(_) => true, - GenericArgKind::Lifetime(_) => false, + GenericArgKind::Lifetime(_) | GenericArgKind::Constness(_) => false, }) .count(); debug!(" => type length={}", type_length); @@ -1382,6 +1382,7 @@ fn create_mono_items_for_default_impls<'tcx>( let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), + GenericParamDefKind::Constness => ty::ConstnessArg::Not.into(), GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 5560d44aa0d52..2a5fd8c1419ec 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -132,11 +132,9 @@ where fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { match predicate.kind().skip_binder() { - ty::PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: _, - polarity: _, - }) => self.visit_trait(trait_ref), + ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { + self.visit_trait(trait_ref) + } ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { term.visit_with(self)?; self.visit_projection_ty(projection_ty) @@ -848,7 +846,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { fn generics(&mut self) -> &mut Self { for param in &self.ev.tcx.generics_of(self.item_def_id).params { match param.kind { - GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Constness | GenericParamDefKind::Lifetime => {} GenericParamDefKind::Type { has_default, .. } => { if has_default { self.visit(self.ev.tcx.type_of(param.def_id)); @@ -1167,7 +1165,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { self.tcx.types.never, ); - for (trait_predicate, _, _) in bounds.trait_bounds { + for (trait_predicate, _) in bounds.trait_bounds { if self.visit_trait(trait_predicate.skip_binder()).is_break() { return; } @@ -1676,7 +1674,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { fn generics(&mut self) -> &mut Self { for param in &self.tcx.generics_of(self.item_def_id).params { match param.kind { - GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Constness | GenericParamDefKind::Lifetime => {} GenericParamDefKind::Type { has_default, .. } => { if has_default { self.visit(self.tcx.type_of(param.def_id)); diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 333dc5aa668b0..20e0011428f64 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -233,16 +233,6 @@ macro_rules! get_provider { }; } -macro_rules! opt_remap_env_constness { - ([][$name:ident]) => {}; - ([(remap_env_constness) $($rest:tt)*][$name:ident]) => { - let $name = $name.without_const(); - }; - ([$other:tt $($modifiers:tt)*][$name:ident]) => { - opt_remap_env_constness!([$($modifiers)*][$name]) - }; -} - macro_rules! define_queries { (<$tcx:tt> $($(#[$attr:meta])* @@ -259,7 +249,6 @@ macro_rules! define_queries { // Create an eponymous constructor for each query. $(#[allow(nonstandard_style)] $(#[$attr])* pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryStackFrame { - opt_remap_env_constness!([$($modifiers)*][key]); let kind = dep_graph::DepKind::$name; let name = stringify!($name); // Disable visible paths printing for performance reasons. @@ -549,7 +538,6 @@ macro_rules! define_queries_struct { key: query_keys::$name<$tcx>, mode: QueryMode, ) -> Option> { - opt_remap_env_constness!([$($modifiers)*][key]); let qcx = QueryCtxt { tcx, queries: self }; get_query::, _>(qcx, span, key, mode) })* diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 557dbecfabe09..259d5361affb8 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1894,7 +1894,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Some(object_lifetime_default) } GenericParamDefKind::Const { .. } => Some(Set1::Empty), - GenericParamDefKind::Lifetime => None, + GenericParamDefKind::Lifetime | GenericParamDefKind::Constness => { + None + } }) .collect() }) diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 13229a3995c22..591a43378de02 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -871,6 +871,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { self.push("K"); self = c.print(self)?; } + GenericArgKind::Constness(_) => {} } } self.push("E"); diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 8b7e8984a8adb..b6feecef33e2e 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -135,7 +135,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { let obligation = traits::Obligation::new( cause.clone(), self.param_env, - ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + ty::Binder::dummy(trait_ref).to_predicate(tcx), ); if !self.infcx.predicate_may_hold(&obligation) { debug!("overloaded_deref_ty: cannot match obligation"); diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 9d30374f8b8ae..c154f81c5775b 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -115,7 +115,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { cause: traits::ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(self.tcx), }; self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 65ff9ceb67ecb..ca3ba46cd0f50 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -299,7 +299,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { def_id: trait_did, substs: infcx.tcx.mk_substs_trait(ty, &[]), }, - constness: ty::BoundConstness::NotConst, // Auto traits are positive polarity: ty::ImplPolarity::Positive, })); @@ -382,17 +381,12 @@ impl<'tcx> AutoTraitFinder<'tcx> { computed_preds.clone().chain(user_computed_preds.iter().cloned()), ) .map(|o| o.predicate); - new_env = ty::ParamEnv::new( - tcx.mk_predicates(normalized_preds), - param_env.reveal(), - param_env.constness(), - ); + new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal()); } let final_user_env = ty::ParamEnv::new( tcx.mk_predicates(user_computed_preds.into_iter()), user_env.reveal(), - user_env.constness(), ); debug!( "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \ diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 8d7c6b26ba152..1d389ceddee1d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -116,7 +116,7 @@ pub trait InferCtxtExt<'tcx> { &self, param_env: ty::ParamEnv<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>, - constness: ty::BoundConstness, + constness: ty::ConstnessArg, polarity: ty::ImplPolarity, ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>; } @@ -325,11 +325,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { match bound_predicate.skip_binder() { ty::PredicateKind::Trait(trait_predicate) => { let trait_predicate = bound_predicate.rebind(trait_predicate); - let mut trait_predicate = self.resolve_vars_if_possible(trait_predicate); + let trait_predicate = self.resolve_vars_if_possible(trait_predicate); - trait_predicate.remap_constness_diag(obligation.param_env); - let predicate_is_const = ty::BoundConstness::ConstIfConst - == trait_predicate.skip_binder().constness; + let predicate_is_const = + ty::ConstnessArg::Const == trait_predicate.skip_binder().constness(); if self.tcx.sess.has_errors().is_some() && trait_predicate.references_error() @@ -490,11 +489,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty); } - if trait_predicate.is_const_if_const() && obligation.param_env.is_const() { - let non_const_predicate = trait_ref.without_const(); + if trait_predicate.constness() != ty::ConstnessArg::Not { + let non_const_predicate = trait_ref.without_const(self.tcx); let non_const_obligation = Obligation { cause: obligation.cause.clone(), - param_env: obligation.param_env.without_const(), + param_env: obligation.param_env, predicate: non_const_predicate.to_predicate(tcx), recursion_depth: obligation.recursion_depth, }; @@ -504,7 +503,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &format!( "the trait `{}` is implemented for `{}`, \ but that implementation is not `const`", - non_const_predicate.print_modifiers_and_trait_path(), + non_const_predicate.print_only_trait_path(), trait_ref.skip_binder().self_ty(), ), ); @@ -599,7 +598,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { && let Ok((implemented_kind, params)) = self.type_implements_fn_trait( obligation.param_env, trait_ref.self_ty(), - trait_predicate.skip_binder().constness, + trait_predicate.skip_binder().constness(), trait_predicate.skip_binder().polarity, ) { @@ -1276,9 +1275,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, param_env: ty::ParamEnv<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>, - constness: ty::BoundConstness, + _constness: ty::ConstnessArg, polarity: ty::ImplPolarity, ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> { + // TODO: handle constness once the fn traits are const_trait self.commit_if_ok(|_| { for trait_def_id in [ self.tcx.lang_items().fn_trait(), @@ -1298,7 +1298,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { param_env, ty.rebind(ty::TraitPredicate { trait_ref: ty::TraitRef::new(trait_def_id, substs), - constness, polarity, }) .to_predicate(self.tcx), @@ -2351,7 +2350,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { let obligation = Obligation::new( ObligationCause::dummy(), param_env, - cleaned_pred.without_const().to_predicate(selcx.tcx()), + cleaned_pred.to_predicate(selcx.tcx()), ); self.predicate_may_hold(&obligation) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 7c9ee64a0c2b0..78bd643d9653b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -180,7 +180,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { substs[param.index as usize].to_string() } - GenericParamDefKind::Lifetime => continue, + GenericParamDefKind::Lifetime | GenericParamDefKind::Constness => continue, }; let name = param.name; flags.push((name, Some(value))); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b08fc48218602..6a70109aae932 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2501,7 +2501,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ObligationCauseCode::ImplDerivedObligation(ref data) => { let mut parent_trait_pred = self.resolve_vars_if_possible(data.derived.parent_trait_pred); - parent_trait_pred.remap_constness_diag(param_env); let parent_def_id = parent_trait_pred.def_id(); let msg = format!( "required because of the requirements on the impl of `{}` for `{}`", diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 74d2eb17b6b30..7678e2dbf13cb 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -143,7 +143,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( param_env, cause: ObligationCause::misc(span, hir::CRATE_HIR_ID), recursion_depth: 0, - predicate: trait_ref.without_const().to_predicate(infcx.tcx), + predicate: trait_ref.to_predicate(infcx.tcx), }; let result = infcx.predicate_must_hold_modulo_regions(&obligation); @@ -293,11 +293,8 @@ pub fn normalize_param_env_or_error<'tcx>( debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); - let elaborated_env = ty::ParamEnv::new( - tcx.intern_predicates(&predicates), - unnormalized_env.reveal(), - unnormalized_env.constness(), - ); + let elaborated_env = + ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal()); // HACK: we are trying to normalize the param-env inside *itself*. The problem is that // normalization expects its param-env to be already normalized, which means we have @@ -345,11 +342,8 @@ pub fn normalize_param_env_or_error<'tcx>( // predicates here anyway. Keeping them here anyway because it seems safer. let outlives_env: Vec<_> = non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect(); - let outlives_env = ty::ParamEnv::new( - tcx.intern_predicates(&outlives_env), - unnormalized_env.reveal(), - unnormalized_env.constness(), - ); + let outlives_env = + ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal()); let Ok(outlives_predicates) = do_normalize_predicates( tcx, cause, @@ -365,11 +359,7 @@ pub fn normalize_param_env_or_error<'tcx>( let mut predicates = non_outlives_predicates; predicates.extend(outlives_predicates); debug!("normalize_param_env_or_error: final predicates={:?}", predicates); - ty::ParamEnv::new( - tcx.intern_predicates(&predicates), - unnormalized_env.reveal(), - unnormalized_env.constness(), - ) + ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal()) } pub fn fully_normalize<'a, 'tcx, T>( @@ -528,7 +518,7 @@ fn prepare_vtable_segments<'tcx, T>( let mut emit_vptr_on_new_entry = false; let mut visited = util::PredicateSet::new(tcx); - let predicate = trait_ref.without_const().to_predicate(tcx); + let predicate = trait_ref.to_predicate(tcx); let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> = smallvec![(trait_ref, emit_vptr_on_new_entry, None)]; visited.insert(predicate); @@ -696,7 +686,8 @@ fn vtable_entries<'tcx>( InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), GenericParamDefKind::Type { .. } - | GenericParamDefKind::Const { .. } => { + | GenericParamDefKind::Const { .. } + | GenericParamDefKind::Constness => { trait_ref.substs[param.index as usize] } }) @@ -815,11 +806,7 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( let obligation = Obligation::new( ObligationCause::dummy(), ty::ParamEnv::reveal_all(), - ty::Binder::dummy(ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: ty::ImplPolarity::Positive, - }), + ty::Binder::dummy(ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive }), ); let implsrc = tcx.infer_ctxt().enter(|infcx| { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index ac1811244ca5e..c14cc27aded41 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -684,7 +684,6 @@ fn receiver_is_dispatchable<'tcx>( def_id: unsize_did, substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]), }) - .without_const() .to_predicate(tcx); // U: Trait @@ -699,18 +698,14 @@ fn receiver_is_dispatchable<'tcx>( }); ty::Binder::dummy(ty::TraitRef { def_id: unsize_did, substs }) - .without_const() + .without_const(tcx) .to_predicate(tcx) }; let caller_bounds: Vec> = param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]).collect(); - ty::ParamEnv::new( - tcx.intern_predicates(&caller_bounds), - param_env.reveal(), - param_env.constness(), - ) + ty::ParamEnv::new(tcx.intern_predicates(&caller_bounds), param_env.reveal()) }; // Receiver: DispatchFromDyn U]> @@ -719,7 +714,6 @@ fn receiver_is_dispatchable<'tcx>( def_id: dispatch_from_dyn_did, substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]), }) - .without_const() .to_predicate(tcx); Obligation::new(ObligationCause::dummy(), param_env, predicate) diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index ed7d16f7a5419..0b0066636a365 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -371,7 +371,7 @@ impl<'tcx> OnUnimplementedFormatString { GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize].to_string() } - GenericParamDefKind::Lifetime => return None, + GenericParamDefKind::Lifetime | GenericParamDefKind::Constness => return None, }; let name = param.name; Some((name, value)) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index b3e7fbb357828..9dc6a831b7101 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -91,7 +91,8 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { // Returns true if the push was successful, or false if the candidate // was discarded -- this could be because of ambiguity, or because // a higher-priority candidate is already there. - fn push_candidate(&mut self, candidate: ProjectionCandidate<'tcx>) -> bool { + #[tracing::instrument(level = "debug", skip(self, tcx))] + fn push_candidate(&mut self, tcx: TyCtxt<'tcx>, candidate: ProjectionCandidate<'tcx>) -> bool { use self::ProjectionCandidate::*; use self::ProjectionCandidateSet::*; @@ -126,6 +127,15 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { // clauses are the safer choice. See the comment on // `select::SelectionCandidate` and #21974 for more details. match (current, candidate) { + // HACK(fee1-dead) + // If both candidates are the same, except for the constness argument, it is not an ambiguity + (ParamEnv(a), ParamEnv(b)) + if a.required_poly_trait_ref(tcx) + .eq_modulo_constness(&b.required_poly_trait_ref(tcx)) + && a.term() == b.term() => + { + return false; + } (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (), (ParamEnv(..), _) => return false, (_, ParamEnv(..)) => unreachable!(), @@ -1136,7 +1146,7 @@ fn normalize_to_error<'a, 'tcx>( cause, recursion_depth: depth, param_env, - predicate: trait_ref.without_const().to_predicate(selcx.tcx()), + predicate: trait_ref.to_predicate(selcx.tcx()), }; let tcx = selcx.infcx().tcx; let def_id = projection_ty.item_def_id; @@ -1365,7 +1375,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( match is_match { ProjectionMatchesProjection::Yes => { - candidate_set.push_candidate(ctor(data)); + candidate_set.push_candidate(infcx.tcx, ctor(data)); if potentially_unnormalized_candidates && !obligation.predicate.has_infer_types_or_consts() @@ -1565,7 +1575,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( selcx.tcx().require_lang_item(LangItem::Sized, None), selcx.tcx().mk_substs_trait(self_ty, &[]), )) - .without_const() .to_predicate(selcx.tcx()), ), ) => @@ -1636,7 +1645,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( }; if eligible { - if candidate_set.push_candidate(ProjectionCandidate::Select(impl_source)) { + if candidate_set.push_candidate(selcx.tcx(), ProjectionCandidate::Select(impl_source)) { Ok(()) } else { Err(()) @@ -1810,7 +1819,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>( tcx.require_lang_item(LangItem::Sized, None), tcx.mk_substs_trait(self_ty, &[]), )) - .without_const() + .to_poly_trait_predicate() .to_predicate(tcx); obligations.push(Obligation::new( obligation.cause.clone(), diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index db45ee3fed7db..e3150e8e1aabd 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -1,5 +1,3 @@ -use rustc_middle::ty; - use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::{ @@ -67,20 +65,10 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { ) -> Result { let mut _orig_values = OriginalQueryValues::default(); - let param_env = match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Trait(pred) => { - // we ignore the value set to it. - let mut _constness = pred.constness; - obligation - .param_env - .with_constness(_constness.and(obligation.param_env.constness())) - } - // constness has no effect on the given predicate. - _ => obligation.param_env.without_const(), - }; - - let c_pred = self - .canonicalize_query_keep_static(param_env.and(obligation.predicate), &mut _orig_values); + let c_pred = self.canonicalize_query_keep_static( + obligation.param_env.and(obligation.predicate), + &mut _orig_values, + ); // Run canonical query. If overflow occurs, rerun from scratch but this time // in standard trait query mode so that overflow is handled appropriately // within `SelectionContext`. diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index 081308ac73e05..02e9b4d0f0e72 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -30,14 +30,8 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { fn perform_query( tcx: TyCtxt<'tcx>, - mut canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>, + canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>, ) -> Fallible> { - match canonicalized.value.value.predicate.kind().skip_binder() { - ty::PredicateKind::Trait(pred) => { - canonicalized.value.param_env.remap_constness_with(pred.constness); - } - _ => canonicalized.value.param_env = canonicalized.value.param_env.without_const(), - } tcx.type_op_prove_predicate(canonicalized) } } diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs index 56bdeafeecae4..7e956786404df 100644 --- a/compiler/rustc_trait_selection/src/traits/relationships.rs +++ b/compiler/rustc_trait_selection/src/traits/relationships.rs @@ -35,7 +35,6 @@ pub(crate) fn update<'tcx, T>( // (*) binder moved here ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, - constness: tpred.constness, polarity: tpred.polarity, }) }) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 96d83deeeb7ab..b5360e5028a75 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -423,8 +423,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Keep only those bounds which may apply, and propagate overflow if it occurs. for bound in matching_bounds { - // FIXME(oli-obk): it is suspicious that we are dropping the constness and - // polarity here. + // FIXME(oli-obk): it is suspicious that we are dropping the polarity here. let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?; if wc.may_apply() { candidates.vec.push(ParamCandidate(bound)); @@ -758,7 +757,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let obligation = traits::Obligation::new( cause.clone(), param_env, - ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + ty::Binder::dummy(trait_ref).to_predicate(tcx), ); if !self.infcx.predicate_may_hold(&obligation) { return None; @@ -957,7 +956,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) { // If the predicate is `~const Destruct` in a non-const environment, we don't actually need // to check anything. We'll short-circuit checking any obligations in confirmation, too. - if !obligation.is_const() { + if obligation.predicate.constness() == ty::ConstnessArg::Not { candidates.vec.push(ConstDestructCandidate(None)); return; } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4862631980e36..6041ca677cb33 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt}; use rustc_middle::ty::{ToPolyTraitRef, ToPredicate}; use rustc_span::def_id::DefId; +use rustc_span::sym; use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def}; @@ -42,9 +43,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidate: SelectionCandidate<'tcx>, ) -> Result, SelectionError<'tcx>> { - let mut obligation = obligation; - let new_obligation; + // let new_obligation; + // when const_trait_impl not enabled, all const predicates are unimplemented + if obligation.predicate.constness() == ty::ConstnessArg::Const { + if !self.tcx().features().enabled(sym::const_trait_impl) { + return Err(SelectionError::Unimplemented); + } + } + // TODO rm // HACK(const_trait_impl): the surrounding environment is remapped to a non-const context // because nested obligations might be actually `~const` then (incorrectly) requiring // const impls. for example: @@ -62,14 +69,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // CheckPredicate(&A: Super) // CheckPredicate(A: ~const Super) // <- still const env, failure // ``` - if obligation.param_env.is_const() && !obligation.predicate.is_const_if_const() { + /*if obligation.param_env.is_const() && !obligation.predicate.constness().is_const() { new_obligation = TraitObligation { cause: obligation.cause.clone(), - param_env: obligation.param_env.without_const(), + param_env: obligation.param_env, ..*obligation }; obligation = &new_obligation; - } + }*/ match candidate { BuiltinCandidate { has_nested } => { @@ -80,7 +87,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ParamCandidate(param) => { let obligations = self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref)); - Ok(ImplSource::Param(obligations, param.skip_binder().constness)) + Ok(ImplSource::Param(obligations, param.skip_binder().constness())) } ImplCandidate(impl_def_id) => { @@ -95,7 +102,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ProjectionCandidate(idx) => { let obligations = self.confirm_projection_candidate(obligation, idx)?; // FIXME(jschievink): constness - Ok(ImplSource::Param(obligations, ty::BoundConstness::NotConst)) + Ok(ImplSource::Param(obligations, ty::ConstnessArg::Not)) } ObjectCandidate(idx) => { @@ -133,7 +140,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This indicates something like `Trait + Send: Send`. In this case, we know that // this holds because that's what the object type is telling us, and there's really // no additional obligations to prove and no types in particular to unify, etc. - Ok(ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst)) + Ok(ImplSource::Param(Vec::new(), ty::ConstnessArg::Not)) } BuiltinUnsizeCandidate => { @@ -549,6 +556,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) .into() } + GenericParamDefKind::Constness => ty::ConstnessArg::Not.into(), }); let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); let assoc_ty_substs = tcx.intern_substs(&substs); @@ -960,7 +968,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tcx.require_lang_item(LangItem::Sized, None), tcx.mk_substs_trait(source, &[]), )); - nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx))); + nested.push(predicate_to_obligation(tr.to_predicate(tcx))); // If the type is `Foo + 'a`, ensure that the type // being cast to `Foo + 'a` outlives `'a`: @@ -993,6 +1001,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ConstKind::Param(p) => Some(p.index), _ => None, }, + + // TODO confirm that this is correct + GenericArgKind::Constness(_) => None, }; // FIXME(eddyb) cache this (including computing `unsizing_params`) @@ -1098,7 +1109,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { impl_def_id: Option, ) -> Result>, SelectionError<'tcx>> { // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop` - if !obligation.is_const() { + if obligation.predicate.constness() == ty::ConstnessArg::Not { return Ok(ImplSourceConstDestructData { nested: vec![] }); } @@ -1202,9 +1213,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { def_id: self .tcx() .require_lang_item(LangItem::Destruct, None), - substs: self.tcx().mk_substs_trait(nested_ty, &[]), + substs: self.tcx().mk_substs_trait( + nested_ty, + &[ty::ConstnessArg::Const.into()], + ), }, - constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }) .to_predicate(tcx), @@ -1228,9 +1241,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .rebind(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: self.tcx().require_lang_item(LangItem::Destruct, None), - substs: self.tcx().mk_substs_trait(nested_ty, &[]), + substs: self + .tcx() + .mk_substs_trait(nested_ty, &[ty::ConstnessArg::Const.into()]), }, - constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }) .to_predicate(tcx); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2bb53a466caa4..1bac985b4c66e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -785,13 +785,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let stack = self.push_stack(previous_stack, &obligation); - let mut fresh_trait_pred = stack.fresh_trait_pred; - let mut param_env = obligation.param_env; - - fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| { - pred.remap_constness(self.tcx(), &mut param_env); - pred - }); + let fresh_trait_pred = stack.fresh_trait_pred; + let param_env = obligation.param_env; debug!(?fresh_trait_pred); @@ -1196,12 +1191,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for candidate in candidates { // Respect const trait obligations - if obligation.is_const() { + if obligation.predicate.constness() == ty::ConstnessArg::Const { match candidate { // const impl ImplCandidate(def_id) if tcx.constness(def_id) == hir::Constness::Const => {} // const param - ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {} + ParamCandidate(trait_pred) + if trait_pred.constness() != ty::ConstnessArg::Not => + { + debug_assert_eq!(trait_pred.constness(), ty::ConstnessArg::Const); + } // auto trait impl AutoImplCandidate(..) => {} // generator, this will raise error in other places @@ -1309,7 +1308,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn check_candidate_cache( &mut self, - mut param_env: ty::ParamEnv<'tcx>, + param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option>> { // Neither the global nor local cache is aware of intercrate @@ -1320,8 +1319,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return None; } let tcx = self.tcx(); - let mut pred = cache_fresh_trait_pred.skip_binder(); - pred.remap_constness(tcx, &mut param_env); + let pred = cache_fresh_trait_pred.skip_binder(); if self.can_use_global_caches(param_env) { if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) { @@ -1367,15 +1365,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(skip(self, param_env, cache_fresh_trait_pred, dep_node), level = "debug")] fn insert_candidate_cache( &mut self, - mut param_env: ty::ParamEnv<'tcx>, + param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, dep_node: DepNodeIndex, candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>, ) { let tcx = self.tcx(); - let mut pred = cache_fresh_trait_pred.skip_binder(); - - pred.remap_constness(tcx, &mut param_env); + let pred = cache_fresh_trait_pred.skip_binder(); if !self.can_cache_candidate(&candidate) { debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable"); @@ -1649,7 +1645,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (ParamCandidate(other), ParamCandidate(victim)) => { let same_except_bound_vars = other.skip_binder().trait_ref == victim.skip_binder().trait_ref - && other.skip_binder().constness == victim.skip_binder().constness && other.skip_binder().polarity == victim.skip_binder().polarity && !other.skip_binder().trait_ref.has_escaping_bound_vars(); if same_except_bound_vars { @@ -1659,8 +1654,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // probably best characterized as a "hack", since we might prefer to just do our // best to *not* create essentially duplicate candidates in the first place. other.bound_vars().len() <= victim.bound_vars().len() - } else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref - && victim.skip_binder().constness == ty::BoundConstness::NotConst + } else if other + .skip_binder() + .trait_ref + .eq_modulo_constness(&victim.skip_binder().trait_ref) + && victim.skip_binder().constness() == ty::ConstnessArg::Not && other.skip_binder().polarity == victim.skip_binder().polarity { // Drop otherwise equivalent non-const candidates in favor of const candidates. @@ -2159,7 +2157,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx().replace_bound_vars_with_placeholders(obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; - let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id); + let mut impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id); + + placeholder_obligation_trait_ref.normalize_constness_equate(self.tcx(), &mut impl_substs); let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs); @@ -2235,7 +2235,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result>, ()> { - self.infcx + let ret = self + .infcx .at(&obligation.cause, obligation.param_env) // We don't want predicates for opaque types to just match all other types, // if there is an obligation on the opaque type, then that obligation must be met @@ -2244,7 +2245,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .define_opaque_types(false) .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref) .map(|InferOk { obligations, .. }| obligations) - .map_err(|_| ()) + .map_err(|_| ()); + trace!(?ret); + ret } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 2c4a453aefc34..66a89bcd1ce6a 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -507,13 +507,15 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti let mut pretty_predicates = Vec::with_capacity(predicates.len() + types_without_default_bounds.len()); - for (mut p, _) in predicates { + for (p, _) in predicates { if let Some(poly_trait_ref) = p.to_opt_poly_trait_pred() { if Some(poly_trait_ref.def_id()) == sized_trait { types_without_default_bounds.remove(&poly_trait_ref.self_ty().skip_binder()); continue; } + // TODO FIX this + /* if ty::BoundConstness::ConstIfConst == poly_trait_ref.skip_binder().constness { let new_trait_pred = poly_trait_ref.map_bound(|mut trait_pred| { trait_pred.constness = ty::BoundConstness::NotConst; @@ -521,7 +523,7 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti }); p = tcx.mk_predicate(new_trait_pred.map_bound(ty::PredicateKind::Trait)) - } + }*/ } pretty_predicates.push(p.to_string()); } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 3170b29ee6973..24f9d56593bfb 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -98,7 +98,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { let tcx = self.tcx; let trait_ref = item.trait_ref(); - let pred = trait_ref.without_const().to_predicate(tcx); + let pred = trait_ref.to_predicate(tcx); debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); @@ -110,9 +110,13 @@ impl<'tcx> TraitAliasExpander<'tcx> { // Don't recurse if this trait alias is already on the stack for the DFS search. let anon_pred = anonymize_predicate(tcx, pred); - if item.path.iter().rev().skip(1).any(|&(tr, _)| { - anonymize_predicate(tcx, tr.without_const().to_predicate(tcx)) == anon_pred - }) { + if item + .path + .iter() + .rev() + .skip(1) + .any(|&(tr, _)| anonymize_predicate(tcx, tr.to_predicate(tcx)) == anon_pred) + { return false; } @@ -251,7 +255,7 @@ pub fn predicate_for_trait_ref<'tcx>( cause, param_env, recursion_depth, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx), } } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 7b5e1498f2695..483c4193f6016 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -56,8 +56,8 @@ pub fn obligations<'a, 'tcx>( } .into() } - // There is nothing we have to do for lifetimes. - GenericArgKind::Lifetime(..) => return Some(Vec::new()), + // There is nothing we have to do for lifetimes and constness arguments. + GenericArgKind::Lifetime(..) | GenericArgKind::Constness(_) => return Some(Vec::new()), }; let mut wf = @@ -295,11 +295,12 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } /// Pushes the obligations required for `trait_ref` to be WF into `self.out`. + #[instrument(level = "debug", skip(self))] fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) { let tcx = self.infcx.tcx; let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); - debug!("compute_trait_ref obligations {:?}", obligations); + debug!(?obligations); let param_env = self.param_env; let depth = self.recursion_depth; @@ -417,7 +418,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, self.recursion_depth, self.param_env, - ty::Binder::dummy(trait_ref).without_const().to_predicate(self.infcx.tcx), + ty::Binder::dummy(trait_ref).to_predicate(self.infcx.tcx), )); } } @@ -435,6 +436,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // obligations are handled by the parent (e.g. `ty::Ref`). GenericArgKind::Lifetime(_) => continue, + // No WF for constness argument + GenericArgKind::Constness(_) => continue, + GenericArgKind::Const(constant) => { match constant.kind() { ty::ConstKind::Unevaluated(uv) => { @@ -696,12 +700,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } + #[instrument(level = "trace", skip(self))] fn nominal_obligations( &mut self, def_id: DefId, substs: SubstsRef<'tcx>, ) -> Vec> { let predicates = self.infcx.tcx.predicates_of(def_id); + trace!(?predicates); let mut origins = vec![def_id; predicates.predicates.len()]; let mut head = predicates; while let Some(parent) = head.parent { @@ -710,6 +716,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } let predicates = predicates.instantiate(self.infcx.tcx, substs); + trace!(?predicates, "instantiated"); debug_assert_eq!(predicates.predicates.len(), origins.len()); iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev()) diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 497819ce5c567..23f4be5c54eb3 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -740,6 +740,9 @@ fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx ty: tcx.type_of(param.def_id), }) .into(), + ty::GenericParamDefKind::Constness => { + ty::ConstnessArg::Not.into() // TODO Confirm + } }) } @@ -757,6 +760,7 @@ fn binders_for<'tcx>( ty::subst::GenericArgKind::Const(c) => { chalk_ir::VariableKind::Const(c.ty().lower_into(interner)) } + ty::subst::GenericArgKind::Constness(_) => unimplemented!(), }), ) } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index c7c604e14e3ee..94add86c1f097 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -191,6 +191,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi GenericArgKind::Const(..) => { chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner)) } + GenericArgKind::Constness(..) => unimplemented!(), GenericArgKind::Lifetime(lt) => bug!("unexpect well formed predicate: {:?}", lt), }, @@ -565,6 +566,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GenericArg>> for Generic ty::subst::GenericArgKind::Const(c) => { chalk_ir::GenericArgData::Const(c.lower_into(interner)) } + ty::subst::GenericArgKind::Constness(_) => unimplemented!(), } .intern(interner) } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 1d345caf69971..109756a661c9e 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -55,7 +55,6 @@ fn sized_constraint_for_ty<'tcx>( def_id: sized_trait, substs: tcx.mk_substs_trait(ty, &[]), }) - .without_const() .to_predicate(tcx); let predicates = tcx.predicates_of(adtdef.did()).predicates; if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] } @@ -134,78 +133,8 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { let local_did = def_id.as_local(); let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); - let constness = match hir_id { - Some(hir_id) => match tcx.hir().get(hir_id) { - hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) - if tcx.is_const_default_method(def_id) => - { - hir::Constness::Const - } - - hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) - | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(..), .. - }) - | hir::Node::AnonConst(_) - | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) - | hir::Node::ImplItem(hir::ImplItem { - kind: - hir::ImplItemKind::Fn( - hir::FnSig { - header: hir::FnHeader { constness: hir::Constness::Const, .. }, - .. - }, - .., - ), - .. - }) => hir::Constness::Const, - - hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::TyAlias(..) | hir::ImplItemKind::Fn(..), - .. - }) => { - let parent_hir_id = tcx.hir().get_parent_node(hir_id); - match tcx.hir().get(parent_hir_id) { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), - .. - }) => *constness, - _ => span_bug!( - tcx.def_span(parent_hir_id.owner), - "impl item's parent node is not an impl", - ), - } - } - - hir::Node::Item(hir::Item { - kind: - hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), - .. - }) - | hir::Node::TraitItem(hir::TraitItem { - kind: - hir::TraitItemKind::Fn( - hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, - .., - ), - .. - }) - | hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), - .. - }) => *constness, - - _ => hir::Constness::NotConst, - }, - None => hir::Constness::NotConst, - }; - - let unnormalized_env = ty::ParamEnv::new( - tcx.intern_predicates(&predicates), - traits::Reveal::UserFacing, - constness, - ); + let unnormalized_env = + ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing); let body_id = hir_id.map_or(hir::CRATE_HIR_ID, |id| { tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) @@ -323,6 +252,8 @@ fn well_formed_types_in_env<'tcx>( // FIXME(eddyb) support const generics in Chalk GenericArgKind::Const(_) => None, + + GenericArgKind::Constness(_) => None, } }); diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 612dc38452188..59048792ba46f 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -189,6 +189,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Option>, arg_count: &GenericArgCountResult, ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>, + constness: Option, ) -> SubstsRef<'tcx> { // Collect the segments of the path; we need to substitute arguments // for parameters throughout the entire path (wherever there are @@ -205,6 +206,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // methods in `subst.rs`, so that we can iterate over the arguments and // parameters in lock-step linearly, instead of trying to match each pair. let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); + let mut has_constness = false; // Iterate over each segment of the path. while let Some((def_id, defs)) = stack.pop() { let mut params = defs.params.iter().peekable(); @@ -212,7 +214,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // If we have already computed substitutions for parents, we can use those directly. while let Some(¶m) = params.peek() { if let Some(&kind) = parent_substs.get(param.index as usize) { - substs.push(kind); + if let subst::GenericArgKind::Constness(ty::ConstnessArg::Infer) = kind.unpack() + { + substs.push(ctx.inferred_kind(None, param, false, None)) + } else { + substs.push(kind); + } + if let subst::GenericArgKind::Constness(_) = kind.unpack() { + has_constness = true; + } params.next(); } else { break; @@ -224,11 +234,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(¶m) = params.peek() { if param.index == 0 { if let GenericParamDefKind::Type { .. } = param.kind { - substs.push( - self_ty - .map(|ty| ty.into()) - .unwrap_or_else(|| ctx.inferred_kind(None, param, true)), - ); + substs.push(self_ty.map(|ty| ty.into()).unwrap_or_else(|| { + ctx.inferred_kind(None, param, true, constness) + })); params.next(); } } @@ -277,7 +285,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) => { // We expected a lifetime argument, but got a type or const // argument. That means we're inferring the lifetimes. - substs.push(ctx.inferred_kind(None, param, infer_args)); + substs.push(ctx.inferred_kind(None, param, infer_args, constness)); force_infer_lt = Some((arg, param)); params.next(); } @@ -374,7 +382,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (None, Some(¶m)) => { // If there are fewer arguments than parameters, it means // we're inferring the remaining arguments. - substs.push(ctx.inferred_kind(Some(&substs), param, infer_args)); + substs.push(ctx.inferred_kind(Some(&substs), param, infer_args, constness)); params.next(); } @@ -382,7 +390,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } - + if !has_constness && let Some(constness) = constness { + if let ty::ConstnessArg::Const = constness { + substs.push(constness.into()); + } + } tcx.intern_substs(&substs) } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 1d4e64b6bfc30..24d9f4d429b34 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -196,6 +196,7 @@ pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> { substs: Option<&[subst::GenericArg<'tcx>]>, param: &ty::GenericParamDef, infer_args: bool, + constness: Option, ) -> subst::GenericArg<'tcx>; } @@ -282,6 +283,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, + None, ); let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args()); @@ -333,6 +335,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option>, + constness: Option, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, @@ -372,7 +375,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // here and so associated type bindings will be handled regardless of whether there are any // non-`Self` generic parameters. if generics.params.is_empty() { - return (tcx.intern_substs(&[]), arg_count); + return ( + tcx.intern_substs(&if let Some(ty::ConstnessArg::Const) = constness { + vec![ty::ConstnessArg::Const.into()] + } else { + vec![] + }), + arg_count, + ); } let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self); @@ -487,6 +497,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { substs: Option<&[subst::GenericArg<'tcx>]>, param: &ty::GenericParamDef, infer_args: bool, + constness: Option, ) -> subst::GenericArg<'tcx> { let tcx = self.astconv.tcx(); match param.kind { @@ -562,6 +573,31 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } + GenericParamDefKind::Constness => { + constness + .unwrap_or_else(|| match self.astconv.item_def_id() { + // no information available + // TODO: fall back to `Not`? + None => { + trace!("uh oh"); + if infer_args { + ty::ConstnessArg::Infer + } else { + ty::ConstnessArg::Not + } + } + Some(context) => { + if tcx.generics_of(context).has_constness_param() { + ty::ConstnessArg::Const + } else { + // TODO: should use `Required` if we're in a const context + // like `const`/`static` item initializers. + ty::ConstnessArg::Not + } + } + }) + .into() + } } } } @@ -584,6 +620,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, &arg_count, &mut substs_ctx, + constness, ); self.complain_about_missing_type_params( @@ -671,6 +708,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, + None, ) .0 } @@ -682,10 +720,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// /// If the `projections` argument is `None`, then assoc type bindings like `Foo` /// are disallowed. Otherwise, they are pushed onto the vector given. + #[instrument(level = "debug", skip(self))] pub fn instantiate_mono_trait_ref( &self, trait_ref: &hir::TraitRef<'_>, self_ty: Ty<'tcx>, + constness: hir::Constness, ) -> ty::TraitRef<'tcx> { self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {}); @@ -695,6 +735,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_ref.path.segments.last().unwrap(), true, + match constness { + // TODO check this again + hir::Constness::Const => ty::ConstnessArg::Const, + hir::Constness::NotConst => ty::ConstnessArg::Not, + }, ) } @@ -703,7 +748,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir_id: hir::HirId, span: Span, binding_span: Option, - constness: ty::BoundConstness, + constness: ty::ConstnessArg, bounds: &mut Bounds<'tcx>, speculative: bool, trait_ref_span: Span, @@ -721,6 +766,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, Some(self_ty), + Some(constness), ); let tcx = self.tcx(); @@ -733,7 +779,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); debug!(?poly_trait_ref, ?assoc_bindings); - bounds.trait_bounds.push((poly_trait_ref, span, constness)); + bounds.trait_bounds.push((poly_trait_ref, span)); let mut dup_bindings = FxHashMap::default(); for binding in &assoc_bindings { @@ -777,7 +823,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, trait_ref: &hir::TraitRef<'_>, span: Span, - constness: ty::BoundConstness, + constness: ty::ConstnessArg, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, @@ -819,7 +865,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { bounds: &mut Bounds<'tcx>, ) { let binding_span = Some(span); - let constness = ty::BoundConstness::NotConst; + let constness = ty::ConstnessArg::Not; let speculative = false; let trait_ref_span = span; let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span)); @@ -849,6 +895,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment<'_>, is_impl: bool, + constness: ty::ConstnessArg, ) -> ty::TraitRef<'tcx> { let (substs, _) = self.create_substs_for_ast_trait_ref( span, @@ -856,6 +903,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_segment, is_impl, + constness, ); let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args()); if let Some(b) = assoc_bindings.first() { @@ -872,6 +920,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, is_impl: bool, + constness: ty::ConstnessArg, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl); @@ -883,6 +932,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_segment.args(), trait_segment.infer_args, Some(self_ty), + Some(constness), ) } @@ -990,8 +1040,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match ast_bound { hir::GenericBound::Trait(poly_trait_ref, modifier) => { let constness = match modifier { - hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst, - hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, + hir::TraitBoundModifier::MaybeConst => ty::ConstnessArg::Const, + hir::TraitBoundModifier::None => ty::ConstnessArg::Not, hir::TraitBoundModifier::Maybe => continue, }; @@ -1327,7 +1377,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } = self.instantiate_poly_trait_ref( &trait_bound.trait_ref, trait_bound.span, - ty::BoundConstness::NotConst, + ty::ConstnessArg::Not, dummy_self, &mut bounds, false, @@ -1339,7 +1389,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. let expanded_traits = - traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b))); + traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().copied()); let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); @@ -1379,7 +1429,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let trait_alias_span = bounds .trait_bounds .iter() - .map(|&(trait_ref, _, _)| trait_ref.def_id()) + .map(|(trait_ref, _)| trait_ref.def_id()) .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) .map(|trait_ref| tcx.def_span(trait_ref)); tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); @@ -1410,10 +1460,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let regular_traits_refs_spans = bounds .trait_bounds .into_iter() - .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); + .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); - for (base_trait_ref, span, constness) in regular_traits_refs_spans { - assert_eq!(constness, ty::BoundConstness::NotConst); + for (base_trait_ref, span) in regular_traits_refs_spans { + assert_eq!(base_trait_ref.skip_binder().constness(), ty::ConstnessArg::Not); for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) { debug!( @@ -2093,8 +2143,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("qpath_to_ty: self_type={:?}", self_ty); - let trait_ref = - self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false); + let trait_ref = self.ast_path_to_mono_trait_ref( + span, + trait_def_id, + self_ty, + trait_segment, + false, + ty::ConstnessArg::Not, + ); let item_substs = self.create_substs_for_associated_item( tcx, @@ -2656,6 +2712,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &GenericArgs::none(), true, None, + None, ); EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id))) .subst(tcx, substs) @@ -2896,8 +2953,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) = hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") }; - let trait_ref = - self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty)); + let trait_ref = self.instantiate_mono_trait_ref( + i.of_trait.as_ref()?, + self.ast_ty_to_ty(i.self_ty), + hir::Constness::NotConst, + ); let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind( tcx, diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 6a28bb16a20ac..8a21c39ee462f 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -29,7 +29,7 @@ pub struct Bounds<'tcx> { /// A list of trait bounds. So if you had `T: Debug` this would be /// `T: Debug`. Note that the self-type is explicit here. - pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>, + pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span)>, /// A list of projection equality bounds. So if you had `T: /// Iterator` this would include ` Bounds<'tcx> { def_id: sized, substs: tcx.mk_substs_trait(param_ty, &[]), }); - (trait_ref.without_const().to_predicate(tcx), span) + (trait_ref.to_predicate(tcx), span) }) }); @@ -75,11 +75,10 @@ impl<'tcx> Bounds<'tcx> { .to_predicate(tcx); (pred, span) }); - let trait_bounds = - self.trait_bounds.iter().map(move |&(bound_trait_ref, span, constness)| { - let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx); - (predicate, span) - }); + let trait_bounds = self.trait_bounds.iter().map(move |&(bound_trait_ref, span)| { + let predicate = bound_trait_ref.to_predicate(tcx); + (predicate, span) + }); let projection_bounds = self .projection_bounds .iter() diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 79e402b542a60..82e2fe237cd07 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -523,7 +523,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_id: t.def_id(), substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]), }, - constness: t.constness, polarity: t.polarity, })); let obl = Obligation::new( diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index dfcd35d2178e7..1cdee4c13a667 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -84,6 +84,7 @@ pub(super) fn check_fn<'a, 'tcx>( can_be_generator: Option, return_type_pre_known: bool, ) -> (FnCtxt<'a, 'tcx>, Option>) { + debug!(?body.value.hir_id); // Create the function context. This is either derived from scratch or, // in the case of closures, based on the outer context. let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id); diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 1681e6af81239..1e7f0b8cc61cd 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -81,7 +81,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let generator_types = check_fn( self, - self.param_env.without_const(), + self.param_env, liberated_sig, decl, expr.hir_id, diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 2bfb9343877a4..f6c7e25fd94a0 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -205,11 +205,8 @@ fn compare_predicate_entailment<'tcx>( // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id); - let param_env = ty::ParamEnv::new( - tcx.intern_predicates(&hybrid_preds.predicates), - Reveal::UserFacing, - hir::Constness::NotConst, - ); + let param_env = + ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing); let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); tcx.infer_ctxt().enter(|infcx| { @@ -837,11 +834,15 @@ fn compare_synthetic_generics<'tcx>( let trait_m_generics = tcx.generics_of(trait_m.def_id); let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind { GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None, + GenericParamDefKind::Constness + | GenericParamDefKind::Lifetime + | GenericParamDefKind::Const { .. } => None, }); let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| match param.kind { GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None, + GenericParamDefKind::Constness + | GenericParamDefKind::Lifetime + | GenericParamDefKind::Const { .. } => None, }); for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in iter::zip(impl_m_type_params, trait_m_type_params) @@ -1012,7 +1013,9 @@ fn compare_generic_param_kinds<'tcx>( // this is exhaustive so that anyone adding new generic param kinds knows // to make sure this error is reported for them. (Const { .. }, Const { .. }) | (Type { .. }, Type { .. }) => false, - (Lifetime { .. }, _) | (_, Lifetime { .. }) => unreachable!(), + (Constness, _) | (_, Constness) | (Lifetime { .. }, _) | (_, Lifetime { .. }) => { + unreachable!() + } } { let param_impl_span = tcx.def_span(param_impl.def_id); let param_trait_span = tcx.def_span(param_trait.def_id); @@ -1032,7 +1035,7 @@ fn compare_generic_param_kinds<'tcx>( format!("{} const parameter of type `{}`", prefix, tcx.type_of(param.def_id)) } Type { .. } => format!("{} type parameter", prefix), - Lifetime { .. } => unreachable!(), + Constness | Lifetime { .. } => unreachable!(), }; let trait_header_span = tcx.def_ident_span(tcx.parent(trait_item.def_id)).unwrap(); @@ -1239,11 +1242,8 @@ fn compare_type_predicate_entailment<'tcx>( debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds); let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); - let param_env = ty::ParamEnv::new( - tcx.intern_predicates(&hybrid_preds.predicates), - Reveal::UserFacing, - hir::Constness::NotConst, - ); + let param_env = + ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing); let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause.clone()); tcx.infer_ctxt().enter(|infcx| { let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); @@ -1378,6 +1378,7 @@ pub fn check_type_bounds<'tcx>( }) .into() } + GenericParamDefKind::Constness => ty::ConstnessArg::Const.into(), }); let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); let impl_ty_substs = tcx.intern_substs(&substs); @@ -1423,11 +1424,7 @@ pub fn check_type_bounds<'tcx>( .to_predicate(tcx), ), }; - ty::ParamEnv::new( - tcx.intern_predicates(&predicates), - Reveal::UserFacing, - param_env.constness(), - ) + ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing) }; debug!(?normalize_param_env); diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 72095c408075c..7e0aaf9b85ef6 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -4,7 +4,7 @@ use crate::hir::def_id::{DefId, LocalDefId}; use rustc_errors::{struct_span_err, ErrorGuaranteed}; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::relate::{super_relate_constness, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::IgnoreRegions; use rustc_middle::ty::{self, Predicate, Ty, TyCtxt}; @@ -186,8 +186,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( // onto one that ignores the constness. This is equivalent to saying that // we match a `Trait` bound on the struct with a `Trait` or `~const Trait` // in the impl. - let non_const_a = - ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..a }; + let non_const_a = a.without_const(tcx); relator.relate(predicate.rebind(non_const_a), p.rebind(b)).is_ok() } (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => { @@ -324,4 +323,11 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> { Ok(a) } + fn constness_args( + &mut self, + a: ty::ConstnessArg, + b: ty::ConstnessArg, + ) -> RelateResult<'tcx, ty::ConstnessArg> { + super_relate_constness(self, a, b) + } } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 30b76b922c77a..d07995535b3a3 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1312,7 +1312,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let body = self.tcx.hir().body(anon_const.body); // Create a new function context. - let fcx = FnCtxt::new(self, self.param_env.with_const(), body.value.hir_id); + let fcx = FnCtxt::new(self, self.param_env, body.value.hir_id); crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body); let ty = fcx.check_expr_with_expectation(&body.value, expected); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index d15d40bc24756..fe0d792c92ae3 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -193,9 +193,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { substs: InternalSubsts::for_item(self.tcx, method.def_id, |param, _| { let i = param.index as usize; if i < method_generics.parent_count { - self.infcx.var_for_def(DUMMY_SP, param) + self.infcx.var_for_def(DUMMY_SP, param, Some(self.constness)) } else { - method.substs[i] + *method.substs.get(i).unwrap_or_else(|| { + span_bug!( + self.tcx.hir().span(hir_id), + "{:#?}\n{:#?}\ni: {}", + method, + method_generics, + i + ) + }) } }), user_self_ty: None, // not relevant here @@ -837,6 +845,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expect_args } + #[tracing::instrument(level = "debug", skip(self))] pub(in super::super) fn resolve_lang_item_path( &self, lang_item: hir::LangItem, @@ -1401,6 +1410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { substs: Option<&[subst::GenericArg<'tcx>]>, param: &ty::GenericParamDef, infer_args: bool, + constness: Option, ) -> subst::GenericArg<'tcx> { let tcx = self.fcx.tcx(); match param.kind { @@ -1421,7 +1431,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This case also occurs as a result of some malformed input, e.g. // a lifetime argument being given instead of a type parameter. // Using inference instead of `Error` gives better error messages. - self.fcx.var_for_def(self.span, param) + self.fcx.var_for_def(self.span, param, None) } } GenericParamDefKind::Const { has_default } => { @@ -1430,9 +1440,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .subst(tcx, substs.unwrap()) .into() } else { - self.fcx.var_for_def(self.span, param) + self.fcx.var_for_def(self.span, param, None) } } + GenericParamDefKind::Constness => match constness { + None => self.fcx.constness().into(), + Some(constness) => constness.into(), + }, } } } @@ -1452,6 +1466,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer_args_for_err: &infer_args_for_err, segments, }, + Some(self.constness()), ) }); assert!(!substs.has_escaping_bound_vars()); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index 05bcc710e1625..22ccecad01ff2 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -118,6 +118,7 @@ pub struct FnCtxt<'a, 'tcx> { /// True if the return type has an Opaque type pub(super) return_type_has_opaque: bool, + constness: ty::ConstnessArg, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -126,7 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, ) -> FnCtxt<'a, 'tcx> { - FnCtxt { + let fcx = FnCtxt { body_id, param_env, err_count_on_creation: inh.tcx.sess.err_count(), @@ -145,7 +146,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { inh, return_type_pre_known: true, return_type_has_opaque: false, - } + constness: { + fn get_constness(tcx: TyCtxt<'_>, did: DefId) -> ty::ConstnessArg { + if tcx.is_const_fn_raw(did) + || tcx.is_const_default_method(did) + || tcx.def_kind(did) == hir::def::DefKind::Const + { + trace!("const"); + ty::ConstnessArg::Const + } else { + trace!("not const"); + ty::ConstnessArg::Not + } + } + if body_id.is_owner() { + let did = body_id.expect_owner(); + get_constness(inh.tcx, did.to_def_id()) + } else if let Some(hir::Node::Expr(hir::Expr { kind, .. })) = + inh.tcx.hir().find(body_id) + { + if let hir::ExprKind::Closure { .. } = kind { + ty::ConstnessArg::Not + } else { + get_constness(inh.tcx, body_id.owner.to_def_id()) + } + } else { + ty::ConstnessArg::Not + } + }, + }; + let constness = fcx.constness; + trace!(?constness); + fcx } pub fn cause(&self, span: Span, code: ObligationCauseCode<'tcx>) -> ObligationCause<'tcx> { @@ -163,6 +195,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn errors_reported_since_creation(&self) -> bool { self.tcx.sess.err_count() > self.err_count_on_creation } + + pub fn constness(&self) -> ty::ConstnessArg { + self.constness + } } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { @@ -222,7 +258,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { if let Some(param) = param { - if let GenericArgKind::Type(ty) = self.var_for_def(span, param).unpack() { + if let GenericArgKind::Type(ty) = self.var_for_def(span, param, None).unpack() { return ty; } unreachable!() @@ -241,7 +277,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { span: Span, ) -> Const<'tcx> { if let Some(param) = param { - if let GenericArgKind::Const(ct) = self.var_for_def(span, param).unpack() { + if let GenericArgKind::Const(ct) = self.var_for_def(span, param, None).unpack() { return ct; } unreachable!() diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 863a981134f24..b0e6c542f07bd 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -851,9 +851,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { recursion_depth: 0, predicate: ty::Binder::dummy(ty::TraitRef { def_id: clone_trait_did, - substs: self.tcx.mk_substs([expected_ty.into()].iter()), + substs: self.tcx.mk_substs_trait(expected_ty.into(), &[]), }) - .without_const() .to_predicate(self.tcx), }) { diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index b14f3d6de4ef1..971246d399e98 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -345,7 +345,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. - assert_eq!(generics.parent_count, parent_substs.len()); + assert!(generics.expected_parent_count().contains(&parent_substs.len())); struct MethodSubstsCtxt<'a, 'tcx> { cfcx: &'a ConfirmContext<'a, 'tcx>, @@ -397,8 +397,19 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { _substs: Option<&[subst::GenericArg<'tcx>]>, param: &ty::GenericParamDef, _infer_args: bool, + constness: Option, ) -> subst::GenericArg<'tcx> { - self.cfcx.var_for_def(self.cfcx.span, param) + if let ty::GenericParamDefKind::Constness = param.kind { + let constness = if let Some(constness) = constness { + constness + } else { + self.cfcx.fcx.constness() + }; + debug!(?constness); + constness.into() + } else { + self.cfcx.var_for_def(self.cfcx.span, param, None) + } } } >::create_substs_for_generic_args( @@ -409,6 +420,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { None, &arg_count_correct, &mut MethodSubstsCtxt { cfcx: self, pick, seg }, + None, ) } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index c0b3a23fde437..d3e7607c263d3 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -284,7 +284,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Construct a trait-reference `self_ty : Trait` let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {} + GenericParamDefKind::Constness + | GenericParamDefKind::Lifetime + | GenericParamDefKind::Const { .. } => {} GenericParamDefKind::Type { .. } => { if param.index == 0 { return self_ty.into(); @@ -293,7 +295,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.var_for_def(span, param) + self.var_for_def(span, param, Some(self.constness())) }); let trait_ref = ty::TraitRef::new(trait_def_id, substs); @@ -305,7 +307,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, self.body_id, self.param_env, - poly_trait_ref.without_const().to_predicate(self.tcx), + poly_trait_ref.to_predicate(self.tcx), ), substs, ) @@ -323,7 +325,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Construct a trait-reference `self_ty : Trait` let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {} + GenericParamDefKind::Constness + | GenericParamDefKind::Lifetime + | GenericParamDefKind::Const { .. } => {} GenericParamDefKind::Type { .. } => { if param.index == 0 { return self_ty.into(); @@ -332,7 +336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.var_for_def(span, param) + self.var_for_def(span, param, Some(self.constness())) }); let trait_ref = ty::TraitRef::new(trait_def_id, substs); @@ -351,7 +355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ), self.param_env, - poly_trait_ref.without_const().to_predicate(self.tcx), + poly_trait_ref.to_predicate(self.tcx), ), substs, ) @@ -450,7 +454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let def_id = method_item.def_id; let generics = tcx.generics_of(def_id); - assert_eq!(generics.params.len(), 0); + assert!(generics.params.len() <= generics.has_constness as usize); // no generics except for constness debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); let mut obligations = vec![]; diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 2de225303560c..ac5929e62aa59 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -1546,11 +1546,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } } - let predicate = - ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx); + let predicate = ty::Binder::dummy(trait_ref).to_predicate(self.tcx); parent_pred = Some(predicate); let obligation = traits::Obligation::new(cause, self.param_env, predicate); + trace!(?obligation); if !self.predicate_may_hold(&obligation) { + trace!("predicate does not hold"); result = ProbeResult::NoMatch; if self.probe(|_| { match self.select_trait_candidate(trait_ref) { @@ -1782,7 +1783,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // method yet. So create fresh variables here for those too, // if there are any. let generics = self.tcx.generics_of(method); - assert_eq!(substs.len(), generics.parent_count as usize); + assert!( + generics.expected_parent_count().contains(&substs.len()), + "substs: {:#?}\ngenerics: {:#?}", + substs, + generics + ); let xform_fn_sig = if generics.params.is_empty() { fn_sig.subst(self.tcx, substs) @@ -1797,8 +1803,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // In general, during probe we erase regions. self.tcx.lifetimes.re_erased.into() } - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { - self.var_for_def(self.span, param) + GenericParamDefKind::Constness + | GenericParamDefKind::Type { .. } + | GenericParamDefKind::Const { .. } => { + self.var_for_def(self.span, param, Some(self.constness())) } } } @@ -1834,6 +1842,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }; self.next_const_var(self.tcx.type_of(param.def_id), origin).into() } + // there is no need to require constness even when we are in a const context. + // just check if the trait is implemented. + GenericParamDefKind::Constness => ty::ConstnessArg::Not.into(), }) } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 7bf167426f748..345cdef2a31b3 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, self.body_id, self.param_env, - poly_trait_ref.without_const().to_predicate(tcx), + poly_trait_ref.to_predicate(tcx), ); self.predicate_may_hold(&obligation) }) diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index dee58791cec18..ac3dc149e2936 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -963,7 +963,10 @@ fn has_expected_num_generic_args<'tcx>( ) -> bool { trait_did.map_or(true, |trait_did| { let generics = tcx.generics_of(trait_did); - generics.count() == expected + if generics.has_self { 1 } else { 0 } + generics.count() + == expected + + if generics.has_self { 1 } else { 0 } + + if generics.has_constness { 1 } else { 0 } }) } diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 0887c27ea360c..982e46240d477 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -859,6 +859,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.lookup_op_method_in_trait(span, opname, trait_did, lhs_ty, other_ty, other_ty_expr) }); + debug!("lookup_op_method(method={method:?}"); + match (method, trait_did) { (Some(ok), _) => { let method = self.register_infer_ok_obligations(ok); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 5621cf2e1a4b5..90f3bc0aac4e0 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -486,7 +486,7 @@ fn augment_param_env<'tcx>( tcx.mk_predicates(param_env.caller_bounds().iter().chain(new_predicates.iter().cloned())); // FIXME(compiler-errors): Perhaps there is a case where we need to normalize this // i.e. traits::normalize_param_env_or_error - ty::ParamEnv::new(bounds, param_env.reveal(), param_env.constness()) + ty::ParamEnv::new(bounds, param_env.reveal()) } /// We use the following trait as an example throughout this function. @@ -1229,8 +1229,10 @@ fn check_impl<'tcx>( // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap(); + trace!(?trait_ref); let trait_ref = fcx.normalize_associated_types_in(ast_trait_ref.path.span, trait_ref); + trace!(?trait_ref, "normalized"); let obligations = traits::wf::trait_obligations( fcx, fcx.param_env, @@ -1281,7 +1283,7 @@ fn check_where_clauses<'tcx, 'fcx>( | GenericParamDefKind::Const { has_default } => { has_default && def.index >= generics.parent_count as u32 } - GenericParamDefKind::Lifetime => unreachable!(), + GenericParamDefKind::Constness | GenericParamDefKind::Lifetime => unreachable!(), }; // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. @@ -1323,8 +1325,8 @@ fn check_where_clauses<'tcx, 'fcx>( } } } - // Doesn't have defaults. - GenericParamDefKind::Lifetime => {} + // Don't have defaults. + GenericParamDefKind::Constness | GenericParamDefKind::Lifetime => {} } } @@ -1369,6 +1371,8 @@ fn check_where_clauses<'tcx, 'fcx>( tcx.mk_param_from_def(param) } + + GenericParamDefKind::Constness => fcx.constness().into(), } }); @@ -1701,11 +1705,7 @@ fn receiver_is_implemented<'tcx>( substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]), }); - let obligation = traits::Obligation::new( - cause, - fcx.param_env, - trait_ref.without_const().to_predicate(fcx.tcx), - ); + let obligation = traits::Obligation::new(cause, fcx.param_env, trait_ref.to_predicate(fcx.tcx)); if fcx.predicate_must_hold_modulo_regions(&obligation) { true @@ -1830,9 +1830,14 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirI let pred = obligation.predicate; // Match the existing behavior. if pred.is_global() && !pred.has_late_bound_regions() { - let pred = fcx.normalize_associated_types_in(span, pred); + let /* mut */ pred = fcx.normalize_associated_types_in(span, pred); let hir_node = fcx.tcx.hir().find(id); + // TODO + /*if fcx.constness() == ty::ConstnessArg::Not { + pred = pred.without_const(fcx.tcx) + }*/ + // only use the span of the predicate clause (#90869) if let Some(hir::Generics { predicates, .. }) = diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 9795be1a912ad..1bcecf7aec89d 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -607,8 +607,7 @@ fn type_param_predicates( // Implied `Self: Trait` and supertrait bounds. if param_id == item_hir_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); - extend = - Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); + extend = Some((identity_trait_ref.to_predicate(tcx), item.span)); } generics } @@ -1519,6 +1518,8 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { params, param_def_id_to_index, has_self: generics.has_self, + has_constness: generics.has_constness, + parent_has_constness: generics.parent_has_constness, has_late_bound_regions: generics.has_late_bound_regions, }; } @@ -1624,13 +1625,17 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { }; let has_self = opt_self.is_some(); + let has_constness = tcx.should_have_constness(def_id); let mut parent_has_self = false; + let mut parent_has_constness = false; let mut own_start = has_self as u32; let parent_count = parent_def_id.map_or(0, |def_id| { let generics = tcx.generics_of(def_id); assert!(!has_self); parent_has_self = generics.has_self; own_start = generics.count() as u32; + // if the parent has a constness param, we inherit it from the parent + parent_has_constness = generics.has_constness; generics.parent_count + generics.params.len() }); @@ -1757,16 +1762,31 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } } + if has_constness && !parent_has_constness { + trace!("adding constness param"); + params.push(ty::GenericParamDef { + name: Symbol::intern(""), + index: type_start + i as u32, + def_id, + pure_wrt_drop: false, + kind: ty::GenericParamDefKind::Constness, + }); + } + let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect(); - ty::Generics { + let generics = ty::Generics { parent: parent_def_id, parent_count, params, param_def_id_to_index, has_self: has_self || parent_has_self, + has_constness: has_constness || parent_has_constness, + parent_has_constness: parent_has_constness, has_late_bound_regions: has_late_bound_regions(tcx, node), - } + }; + trace!("{:#?}", generics); + generics } fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool { @@ -1967,12 +1987,18 @@ fn infer_return_ty_for_fn_sig<'tcx>( } } +#[instrument(level = "debug", skip(tcx))] fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let icx = ItemCtxt::new(tcx, def_id); match tcx.hir().expect_item(def_id.expect_local()).kind { hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| { let selfty = tcx.type_of(def_id); - >::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) + >::instantiate_mono_trait_ref( + &icx, + ast_trait_ref, + selfty, + impl_.constness, + ) }), _ => bug!(), } @@ -2086,7 +2112,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { let span = rustc_span::DUMMY_SP; result.predicates = tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( - ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx), + ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), span, )))); } @@ -2205,7 +2231,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // (see below). Recall that a default impl is not itself an impl, but rather a // set of defaults that can be incorporated into another impl. if let Some(trait_ref) = is_default_impl_trait { - predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id))); + predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id))); } // Collect the region predicates that were declared inline as diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index e7ca70de4ba71..c8ea68d304646 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -155,6 +155,9 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) ); } } + ty::GenericParamDefKind::Constness => { + // TODO: users can't write these, do we have to do anything here? + } } } diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index c46b825f4578d..783206e40bf0d 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -369,11 +369,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc _ if predicate.is_global() => (), // We allow specializing on explicitly marked traits with no associated // items. - ty::PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: _, - }) => { + ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { if !matches!( trait_predicate_kind(tcx, predicate), Some(TraitSpecializationKind::Marker) @@ -411,12 +407,10 @@ fn trait_predicate_kind<'tcx>( ) -> Option { match predicate.kind().skip_binder() { ty::PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, + trait_ref, // TODO review specialization check polarity: _, }) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), - ty::PredicateKind::Trait(_) - | ty::PredicateKind::RegionOutlives(_) + ty::PredicateKind::RegionOutlives(_) | ty::PredicateKind::TypeOutlives(_) | ty::PredicateKind::Projection(_) | ty::PredicateKind::WellFormed(_) diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index f98ae46c58730..93a125c575323 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -569,7 +569,7 @@ pub fn hir_trait_to_predicates<'tcx>( &item_cx, hir_trait, DUMMY_SP, - ty::BoundConstness::NotConst, + ty::ConstnessArg::Not, // TODO Or Param? self_ty, &mut bounds, true, diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs index 257a9520eeb25..04649f82131f5 100644 --- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs +++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs @@ -99,7 +99,11 @@ fn insert_required_predicates_to_be_wf<'tcx>( // No predicates from lifetimes or constants, except potentially // constants' types, but `walk` will get to them as well. - GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue, + GenericArgKind::Constness(_) + | GenericArgKind::Lifetime(_) + | GenericArgKind::Const(_) => { + continue; + } }; match *ty.kind() { diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs index 8fa65d51e3ba1..d25d45b0039e7 100644 --- a/compiler/rustc_typeck/src/outlives/mod.rs +++ b/compiler/rustc_typeck/src/outlives/mod.rs @@ -119,6 +119,10 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { // Generic consts don't impose any constraints. None } + GenericArgKind::Constness(_) => { + // Constness effect doesn't impose any constraints. + None + } } }, )); diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs index b718ca9421336..922854c69f96c 100644 --- a/compiler/rustc_typeck/src/outlives/utils.rs +++ b/compiler/rustc_typeck/src/outlives/utils.rs @@ -128,6 +128,9 @@ pub(crate) fn insert_outlives_predicate<'tcx>( GenericArgKind::Const(_) => { // Generic consts don't impose any constraints. } + GenericArgKind::Constness(_) => { + // Constness effect doesn't impose any constraints. + } } } diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index d79450e1ae707..6f703362c6869 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -189,6 +189,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { GenericArgKind::Const(val) => { self.add_constraints_from_const(current, val, variance_i) } + // Does not contain anything with constraints + GenericArgKind::Constness(_) => {} } } } @@ -354,6 +356,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { GenericArgKind::Const(val) => { self.add_constraints_from_const(current, val, variance) } + GenericArgKind::Constness(_) => {} } } } diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 06dca7e59a2a6..3c2ffd0392d3f 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -106,7 +106,7 @@ use crate::marker::Destruct; #[lang = "clone"] #[rustc_diagnostic_item = "Clone"] #[rustc_trivial_field_reads] -#[const_trait] +#[cfg_attr(not(bootstrap), const_trait)] pub trait Clone: Sized { /// Returns a copy of the value. /// diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 1d3466696ed04..7147475789e62 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -214,7 +214,7 @@ use self::Ordering::*; append_const_msg, ) )] -#[const_trait] +#[cfg_attr(not(bootstrap), const_trait)] #[rustc_diagnostic_item = "PartialEq"] pub trait PartialEq { /// This method tests for `self` and `other` values to be equal, and is used @@ -1053,7 +1053,7 @@ impl PartialOrd for Ordering { append_const_msg, ) )] -#[const_trait] +#[cfg_attr(not(bootstrap), const_trait)] #[rustc_diagnostic_item = "PartialOrd"] pub trait PartialOrd: PartialEq { /// This method returns an ordering between `self` and `other` values if one exists. diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index c5a194b7d0a41..63e11980d3924 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -237,6 +237,7 @@ pub trait FnMut: FnOnce { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] +#[cfg_attr(not(bootstrap), const_trait)] pub trait FnOnce { /// The returned type after the call operator is used. #[lang = "fn_once_output"] diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index fd7ecf3daf316..234c5ac98c41e 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -152,6 +152,7 @@ mod private_slice_index { message = "the type `{T}` cannot be indexed by `{Self}`", label = "slice indices are of type `usize` or ranges of `usize`" )] +#[cfg_attr(not(bootstrap), const_trait)] pub unsafe trait SliceIndex: private_slice_index::Sealed { /// The output type returned by methods. #[stable(feature = "slice_get_slice", since = "1.28.0")] diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index b0c55ca4f5139..d00a56af05155 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -82,8 +82,7 @@ use super::Utf8Error; /// assert_eq!("💖", sparkle_heart); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")] -#[rustc_allow_const_fn_unstable(str_internals)] +#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { // FIXME: This should use `?` again, once it's `const` match run_utf8_validation(v) { diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index e6f006135e29a..9c02e4d9aeca8 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -625,6 +625,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } } GenericParamDefKind::Lifetime { .. } => {} + GenericParamDefKind::Constness => {} GenericParamDefKind::Const { ref mut default, .. } => { // We never want something like `impl` default.take(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fa2efb0041621..b70ad5e82c4bb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -308,7 +308,7 @@ impl<'tcx> Clean<'tcx, Option> for ty::Predicate<'tcx> { impl<'tcx> Clean<'tcx, Option> for ty::PolyTraitPredicate<'tcx> { fn clean(&self, cx: &mut DocContext<'tcx>) -> Option { // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. - if self.skip_binder().constness == ty::BoundConstness::ConstIfConst + if self.skip_binder().constness() != ty::ConstnessArg::Not && Some(self.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() { return None; @@ -439,6 +439,7 @@ fn projection_to_path_segment<'tcx>( impl<'tcx> Clean<'tcx, GenericParamDef> for ty::GenericParamDef { fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericParamDef { let (name, kind) = match self.kind { + ty::GenericParamDefKind::Constness => (self.name, GenericParamDefKind::Constness), ty::GenericParamDefKind::Lifetime => { (self.name, GenericParamDefKind::Lifetime { outlives: vec![] }) } @@ -561,6 +562,7 @@ impl<'tcx> Clean<'tcx, Generics> for hir::Generics<'tcx> { .map(|param| { let param = clean_generic_param(cx, Some(self), param); match param.kind { + GenericParamDefKind::Constness => unreachable!(), GenericParamDefKind::Lifetime { .. } => unreachable!(), GenericParamDefKind::Type { did, ref bounds, .. } => { cx.impl_trait_bounds.insert(did.into(), bounds.clone()); @@ -594,6 +596,7 @@ impl<'tcx> Clean<'tcx, Generics> for hir::Generics<'tcx> { if bounds.is_empty() { for param in &mut generics.params { match param.kind { + GenericParamDefKind::Constness => {} GenericParamDefKind::Lifetime { .. } => {} GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => { if ¶m.name == name { @@ -642,6 +645,7 @@ fn clean_ty_generics<'tcx>( } Some(param.clean(cx)) } + ty::GenericParamDefKind::Constness => None, ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)), }) .collect::>(); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d29ba2dedaf71..5160c1b96c204 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1362,6 +1362,7 @@ impl WherePredicate { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) enum GenericParamDefKind { + Constness, Lifetime { outlives: Vec }, Type { did: DefId, bounds: Vec, default: Option>, synthetic: bool }, Const { did: DefId, ty: Box, default: Option> }, @@ -1386,7 +1387,9 @@ rustc_data_structures::static_assert_size!(GenericParamDef, 56); impl GenericParamDef { pub(crate) fn is_synthetic_type_param(&self) -> bool { match self.kind { - GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false, + GenericParamDefKind::Constness + | GenericParamDefKind::Lifetime { .. } + | GenericParamDefKind::Const { .. } => false, GenericParamDefKind::Type { synthetic, .. } => synthetic, } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 22b1e2335fd84..0161951b04bff 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -84,6 +84,7 @@ pub(crate) fn substs_to_args<'tcx>( let mut ret_val = Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 })); ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() { + GenericArgKind::Constness(_) => None, GenericArgKind::Lifetime(lt) => { Some(GenericArg::Lifetime(lt.clean(cx).unwrap_or(Lifetime::elided()))) } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 9f46ab54d3ece..46487a4b5ebf3 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -190,6 +190,7 @@ impl clean::GenericParamDef { cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| match &self.kind { + clean::GenericParamDefKind::Constness => Ok(()), clean::GenericParamDefKind::Lifetime { outlives } => { write!(f, "{}", self.name)?; diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index db2ad953f6aa0..999b686c3652e 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -363,6 +363,7 @@ impl FromWithTcx for GenericParamDefKind { type_: (*ty).into_tcx(tcx), default: default.map(|x| *x), }, + Constness => GenericParamDefKind::Constness, } } } diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 1168a89a8b2bf..e9355447b2524 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -382,6 +382,7 @@ pub enum GenericParamDefKind { type_: Type, default: Option, }, + Constness, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs index 01ac74feff74d..ddc6ca80c38fe 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs @@ -8,3 +8,4 @@ trait A { #[const_trait] //~ ERROR attribute should be applied fn main() {} +//~^ ERROR `main` function is not allowed to have generic parameters diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs index 24b9235bb9a76..e13903f6182cf 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs @@ -1,5 +1,6 @@ #![feature(const_trait_impl)] +#[const_trait] pub trait Plus { fn plus(self, rhs: Self) -> Self; } @@ -23,7 +24,7 @@ pub const fn add_i32(a: i32, b: i32) -> i32 { pub const fn add_u32(a: u32, b: u32) -> u32 { a.plus(b) //~^ ERROR the trait bound - //~| ERROR cannot call non-const fn + //~| ERROR cannot call } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index 1fc9db277610e..bc92719f6fd60 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -1,17 +1,20 @@ -error[E0277]: the trait bound `u32: ~const Plus` is not satisfied - --> $DIR/call-const-trait-method-fail.rs:24:7 +error[E0277]: the trait bound `u32: Plus` is not satisfied + --> $DIR/call-const-trait-method-fail.rs:25:7 | LL | a.plus(b) - | ^^^^^^^ the trait `~const Plus` is not implemented for `u32` + | ^^^^^^^ the trait `Plus` is not implemented for `u32` | -note: the trait `Plus` is implemented for `u32`, but that implementation is not `const` - --> $DIR/call-const-trait-method-fail.rs:24:7 +note: the trait `Plus` is implemented for `u32`, but that implementation is not `const` + --> $DIR/call-const-trait-method-fail.rs:25:7 | LL | a.plus(b) | ^^^^^^^ + = help: the following other types implement trait `Plus`: + > + > -error[E0015]: cannot call non-const fn `::plus` in constant functions - --> $DIR/call-const-trait-method-fail.rs:24:7 +error[E0015]: cannot call non-const fn `>::plus` in constant functions + --> $DIR/call-const-trait-method-fail.rs:25:7 | LL | a.plus(b) | ^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs index 8df68225d44cd..a9b653f82dd63 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -2,8 +2,7 @@ pub const fn equals_self(t: &T) -> bool { *t == *t - //~^ ERROR can't compare - //~| ERROR cannot call non-const + //~^ ERROR cannot call non-const } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs index 0b981d1621eca..484a2fd4d5702 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs @@ -22,8 +22,7 @@ impl const ConstDefaultFn for ConstImpl { const fn test() { NonConstImpl.a(); - //~^ ERROR the trait bound - //~| ERROR cannot call non-const fn + //~^ ERROR no method named `a` found for struct `NonConstImpl` ConstImpl.a(); } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr index fe788b43a5416..98284d6a239a5 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr @@ -1,24 +1,19 @@ -error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied +error[E0599]: no method named `a` found for struct `NonConstImpl` in the current scope --> $DIR/const-default-method-bodies.rs:24:18 | +LL | struct NonConstImpl; + | -------------------- method `a` not found for this +... LL | NonConstImpl.a(); - | ^^^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl` + | ^ method not found in `NonConstImpl` | -note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const` - --> $DIR/const-default-method-bodies.rs:24:18 - | -LL | NonConstImpl.a(); - | ^^^ - -error[E0015]: cannot call non-const fn `::a` in constant functions - --> $DIR/const-default-method-bodies.rs:24:18 - | -LL | NonConstImpl.a(); - | ^^^ + = help: items from traits can only be used if the trait is implemented and in scope +note: `ConstDefaultFn` defines an item `a`, perhaps you need to implement it + --> $DIR/const-default-method-bodies.rs:4:1 | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | trait ConstDefaultFn: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0015, E0277. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound.rs new file mode 100644 index 0000000000000..60067477e05eb --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound.rs @@ -0,0 +1,13 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn foo(); +} + +const fn foo() { + T::foo(); +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-const-impl-and-call.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-const-impl-and-call.rs new file mode 100644 index 0000000000000..87ff744a28f48 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-const-impl-and-call.rs @@ -0,0 +1,17 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn foo(&self); +} + +struct S; + +impl const Foo for S { + fn foo(&self) {} +} + +const FOO: () = S.foo(); + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-further-normalize.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-further-normalize.rs new file mode 100644 index 0000000000000..e3908eda503f7 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-further-normalize.rs @@ -0,0 +1,23 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn foo(&self); +} + +struct S1; +struct S2; + +impl Foo for S1 { + fn foo(&self) {} +} + +impl const Foo for S2 where S1: ~const Foo { + fn foo(&self) {} +} + +fn main() { + S2.foo(); +} + diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-impl-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-impl-bound.rs new file mode 100644 index 0000000000000..6033927006bef --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-impl-bound.rs @@ -0,0 +1,17 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn foo(); +} + +pub struct W(T); + +impl const Foo for W { + fn foo() { + ::foo(); + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-non-const-impl-and-call.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-non-const-impl-and-call.rs new file mode 100644 index 0000000000000..e928eec48a347 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-non-const-impl-and-call.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn foo(&self); +} + +pub struct S; + +impl Foo for S { + fn foo(&self) {} +} + +fn non_const() { + S.foo(); +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr index 3ca9abb139b86..7e5eb8742160f 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr @@ -1,16 +1,17 @@ -error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied +error[E0277]: the trait bound `NonConst: MyTrait` is not satisfied --> $DIR/cross-crate.rs:15:14 | LL | NonConst.func(); - | ^^^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` + | ^^^^^^ the trait `MyTrait` is not implemented for `NonConst` | -note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const` +note: the trait `MyTrait` is implemented for `NonConst`, but that implementation is not `const` --> $DIR/cross-crate.rs:15:14 | LL | NonConst.func(); | ^^^^^^ + = help: the trait `MyTrait` is implemented for `NonConst` -error[E0015]: cannot call non-const fn `::func` in constant functions +error[E0015]: cannot call non-const fn `>::func` in constant functions --> $DIR/cross-crate.rs:15:14 | LL | NonConst.func(); diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs index fa049ab86ff49..590f0ad3d42a9 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs @@ -12,10 +12,10 @@ fn non_const_context() { } const fn const_context() { - NonConst.func(); //~ ERROR: cannot call non-const fn + NonConst.func(); //~ ERROR: cannot call //[gated]~^ ERROR: the trait bound Const.func(); - //[stock]~^ ERROR: cannot call non-const fn + //[stock]~^ ERROR: cannot call } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr index ea75ad0aeaf8c..00f26cd771765 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -1,4 +1,4 @@ -error[E0015]: cannot call non-const fn `::func` in constant functions +error[E0015]: cannot call non-const fn `>::func` in constant functions --> $DIR/cross-crate.rs:15:14 | LL | NonConst.func(); @@ -6,7 +6,7 @@ LL | NonConst.func(); | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `::func` in constant functions +error[E0015]: cannot call non-const fn `>::func` in constant functions --> $DIR/cross-crate.rs:17:11 | LL | Const.func(); diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs index d798516ff70fd..8bb4e39cc0157 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs @@ -6,8 +6,7 @@ pub trait Tr { fn b(&self) { ().a() - //~^ ERROR the trait bound - //~| ERROR cannot call + //~^ ERROR no method named `a` found for unit type `()` in the current scope } } diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr index 8bb7f0141033d..f0e0eb1e67681 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr @@ -1,24 +1,16 @@ -error[E0277]: the trait bound `(): ~const Tr` is not satisfied +error[E0599]: no method named `a` found for unit type `()` in the current scope --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 | LL | ().a() - | ^^^ the trait `~const Tr` is not implemented for `()` + | ^ method not found in `()` | -note: the trait `Tr` is implemented for `()`, but that implementation is not `const` - --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 - | -LL | ().a() - | ^^^ - -error[E0015]: cannot call non-const fn `<() as Tr>::a` in constant functions - --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 - | -LL | ().a() - | ^^^ + = help: items from traits can only be used if the trait is implemented and in scope +note: `Tr` defines an item `a`, perhaps you need to implement it + --> $DIR/default-method-body-is-const-same-trait-ck.rs:4:1 | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | pub trait Tr { + | ^^^^^^^^^^^^ error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0277. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs index b132c395ac7b4..46f6343002642 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs @@ -6,8 +6,7 @@ pub trait A { pub const fn foo() -> bool { T::assoc() - //~^ ERROR the trait bound - //~| ERROR cannot call non-const fn + //~^ ERROR cannot call non-const fn } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs index b4302f3e75fd4..9ee7caa80c5de 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs @@ -7,12 +7,14 @@ impl T for S {} fn rpit() -> impl ~const T { S } //~^ ERROR `~const` is not allowed +//~| ERROR the trait bound fn apit(_: impl ~const T) {} //~^ ERROR `~const` is not allowed fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } //~^ ERROR `~const` is not allowed +//~| ERROR the trait bound fn apit_assoc_bound(_: impl IntoIterator) {} //~^ ERROR `~const` is not allowed diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr index 033ec21ba8408..47736309d8418 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -7,7 +7,7 @@ LL | fn rpit() -> impl ~const T { S } = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions error: `~const` is not allowed here - --> $DIR/tilde-const-invalid-places.rs:11:17 + --> $DIR/tilde-const-invalid-places.rs:12:17 | LL | fn apit(_: impl ~const T) {} | ^^^^^^^^ @@ -15,7 +15,7 @@ LL | fn apit(_: impl ~const T) {} = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions error: `~const` is not allowed here - --> $DIR/tilde-const-invalid-places.rs:14:50 + --> $DIR/tilde-const-invalid-places.rs:15:50 | LL | fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } | ^^^^^^^^ @@ -23,7 +23,7 @@ LL | fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions error: `~const` is not allowed here - --> $DIR/tilde-const-invalid-places.rs:17:48 + --> $DIR/tilde-const-invalid-places.rs:19:48 | LL | fn apit_assoc_bound(_: impl IntoIterator) {} | ^^^^^^^^ @@ -31,7 +31,7 @@ LL | fn apit_assoc_bound(_: impl IntoIterator) {} = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions error: `~const` is not allowed here - --> $DIR/tilde-const-invalid-places.rs:20:15 + --> $DIR/tilde-const-invalid-places.rs:22:15 | LL | fn generic() {} | ^^^^^^^^ @@ -39,7 +39,7 @@ LL | fn generic() {} = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions error: `~const` is not allowed here - --> $DIR/tilde-const-invalid-places.rs:23:31 + --> $DIR/tilde-const-invalid-places.rs:25:31 | LL | fn where_clause

() where P: ~const T {} | ^^^^^^^^ @@ -47,10 +47,37 @@ LL | fn where_clause

() where P: ~const T {} = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions error: `~const` and `?` are mutually exclusive - --> $DIR/tilde-const-invalid-places.rs:26:25 + --> $DIR/tilde-const-invalid-places.rs:28:25 | LL | struct TildeQuestion(std::marker::PhantomData); | ^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error[E0277]: the trait bound `S: T` is not satisfied + --> $DIR/tilde-const-invalid-places.rs:8:14 + | +LL | fn rpit() -> impl ~const T { S } + | ^^^^^^^^^^^^^ the trait `T` is not implemented for `S` + | +note: the trait `T` is implemented for `S`, but that implementation is not `const` + --> $DIR/tilde-const-invalid-places.rs:8:14 + | +LL | fn rpit() -> impl ~const T { S } + | ^^^^^^^^^^^^^ + = help: the trait `T` is implemented for `S` + +error[E0277]: the trait bound `S: T` is not satisfied + --> $DIR/tilde-const-invalid-places.rs:15:26 + | +LL | fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T` is not implemented for `S` + | +note: the trait `T` is implemented for `S`, but that implementation is not `const` + --> $DIR/tilde-const-invalid-places.rs:15:26 + | +LL | fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: the trait `T` is implemented for `S` + +error: aborting due to 9 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized/issue-30355.rs b/src/test/ui/unsized/issue-30355.rs index 0181109050320..6ff5b37f6e5b9 100644 --- a/src/test/ui/unsized/issue-30355.rs +++ b/src/test/ui/unsized/issue-30355.rs @@ -4,7 +4,6 @@ pub static Y: &'static X = { const Y: &'static [u8] = b""; &X(*Y) //~^ ERROR E0277 - //~| ERROR E0277 }; fn main() {} diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index 176787497ebf2..23d5e353efa33 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -124,6 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path)) }, + GenericArgKind::Constness(_) | GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, }); if contains_sync_guard { diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index ddef7352de889..6c4b261ec0579 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -212,6 +212,7 @@ fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t substs.iter().all(|generic_arg| match generic_arg.unpack() { GenericArgKind::Type(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait), // Lifetimes and const generics are not solid part of ADT and ignored + GenericArgKind::Constness(_) | GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => true, }) } else { diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index f3283588c7320..2ff130a011b47 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -71,6 +71,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult { // No constraints on lifetimes or constants, except potentially // constants' types, but `walk` will get to them as well. + GenericArgKind::Constness(_) | GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue, }; diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index a426fa1b0ffcf..673da988393f1 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -47,7 +47,7 @@ pub fn can_partially_move_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool pub fn contains_ty<'tcx>(ty: Ty<'tcx>, other_ty: Ty<'tcx>) -> bool { ty.walk().any(|inner| match inner.unpack() { GenericArgKind::Type(inner_ty) => other_ty == inner_ty, - GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, + GenericArgKind::Lifetime(_) | GenericArgKind::Constness(_) | GenericArgKind::Const(_) => false, }) } @@ -56,7 +56,7 @@ pub fn contains_ty<'tcx>(ty: Ty<'tcx>, other_ty: Ty<'tcx>) -> bool { pub fn contains_adt_constructor<'tcx>(ty: Ty<'tcx>, adt: AdtDef<'tcx>) -> bool { ty.walk().any(|inner| match inner.unpack() { GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt), - GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, + GenericArgKind::Lifetime(_) | GenericArgKind::Constness(_) | GenericArgKind::Const(_) => false, }) }