From 84a490712aa474a146e619cf15afba22fb652445 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 10 Sep 2023 05:11:37 +0000 Subject: [PATCH 1/2] Implement fallback for effect param --- compiler/rustc_hir_typeck/src/fallback.rs | 64 ++++++++++++---- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 56 +++++++++----- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 6 +- .../src/infer/canonical/canonicalizer.rs | 14 +++- .../rustc_infer/src/infer/canonical/mod.rs | 6 +- compiler/rustc_infer/src/infer/combine.rs | 69 +++++++++++++++-- compiler/rustc_infer/src/infer/freshen.rs | 15 ++++ compiler/rustc_infer/src/infer/generalize.rs | 1 + compiler/rustc_infer/src/infer/mod.rs | 76 +++++++++++++++++-- compiler/rustc_infer/src/infer/undo_log.rs | 3 + compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +- compiler/rustc_middle/src/infer/canonical.rs | 45 +++++++---- compiler/rustc_middle/src/infer/unify_key.rs | 50 ++++++++++++ compiler/rustc_middle/src/ty/consts/kind.rs | 9 ++- compiler/rustc_middle/src/ty/flags.rs | 4 +- compiler/rustc_middle/src/ty/mod.rs | 6 +- .../rustc_middle/src/ty/structural_impls.rs | 8 ++ compiler/rustc_middle/src/ty/sty.rs | 14 ++++ .../src/solve/canonicalize.rs | 3 + .../effects/fallback.rs | 9 +++ 20 files changed, 390 insertions(+), 72 deletions(-) create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 5b5986a349f..97091c39c65 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -4,6 +4,7 @@ use rustc_data_structures::{ graph::{iterate::DepthFirstSearch, vec_graph::VecGraph}, unord::{UnordBag, UnordMap, UnordSet}, }; +use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::ty::{self, Ty}; impl<'tcx> FnCtxt<'_, 'tcx> { @@ -23,22 +24,12 @@ impl<'tcx> FnCtxt<'_, 'tcx> { self.fulfillment_cx.borrow_mut().pending_obligations() ); - // Check if we have any unsolved variables. If not, no need for fallback. - let unsolved_variables = self.unsolved_variables(); - if unsolved_variables.is_empty() { + let fallback_occured = self.fallback_types() || self.fallback_effects(); + + if !fallback_occured { return; } - let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables); - - // We do fallback in two passes, to try to generate - // better error messages. - // The first time, we do *not* replace opaque types. - for ty in unsolved_variables { - debug!("unsolved_variable = {:?}", ty); - self.fallback_if_possible(ty, &diverging_fallback); - } - // We now see if we can make progress. This might cause us to // unify inference variables for opaque types, since we may // have unified some other type variables during the first @@ -65,6 +56,53 @@ impl<'tcx> FnCtxt<'_, 'tcx> { self.select_obligations_where_possible(|_| {}); } + fn fallback_types(&self) -> bool { + // Check if we have any unsolved variables. If not, no need for fallback. + let unsolved_variables = self.unsolved_variables(); + + if unsolved_variables.is_empty() { + return false; + } + + let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables); + + // We do fallback in two passes, to try to generate + // better error messages. + // The first time, we do *not* replace opaque types. + for ty in unsolved_variables { + debug!("unsolved_variable = {:?}", ty); + self.fallback_if_possible(ty, &diverging_fallback); + } + + true + } + + fn fallback_effects(&self) -> bool { + let unsolved_effects = self.unsolved_effects(); + + if unsolved_effects.is_empty() { + return false; + } + + // not setting `fallback_has_occured` here because that field is only used for type fallback + // diagnostics. + + for effect in unsolved_effects { + let expected = self.tcx.consts.true_; + let cause = self.misc(rustc_span::DUMMY_SP); + match self.at(&cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, effect) { + Ok(InferOk { obligations, value: () }) => { + self.register_predicates(obligations); + } + Err(e) => { + bug!("cannot eq unsolved effect: {e:?}") + } + } + } + + true + } + // Tries to apply a fallback to `ty` if it is an unsolved variable. // // - Unconstrained ints are replaced with `i32`. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 28fe2e062e5..694f3f67bab 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1295,17 +1295,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { self.fcx.ty_infer(Some(param), inf.span).into() } - (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { + (&GenericParamDefKind::Const { has_default }, GenericArg::Infer(inf)) => { let tcx = self.fcx.tcx(); - self.fcx - .ct_infer( - tcx.type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - Some(param), - inf.span, - ) - .into() + + if has_default && tcx.has_attr(param.def_id, sym::rustc_host) { + self.fcx.var_for_effect(param) + } else { + self.fcx + .ct_infer( + tcx.type_of(param.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic"), + Some(param), + inf.span, + ) + .into() + } } _ => unreachable!(), } @@ -1324,7 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } GenericParamDefKind::Type { has_default, .. } => { if !infer_args && has_default { - // If we have a default, then we it doesn't matter that we're not + // If we have a default, then it doesn't matter that we're not // inferring the type arguments: we provide the default where any // is missing. tcx.type_of(param.def_id).instantiate(tcx, args.unwrap()).into() @@ -1337,16 +1342,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } GenericParamDefKind::Const { has_default } => { - if !infer_args - && has_default - && !tcx.has_attr(param.def_id, sym::rustc_host) - { - tcx.const_param_default(param.def_id) - .instantiate(tcx, args.unwrap()) - .into() - } else { - self.fcx.var_for_def(self.span, param) + if has_default { + // N.B. this is a bit of a hack. `infer_args` is passed depending on + // whether the user has provided generic args. E.g. for `Vec::new` + // we would have to infer the generic types. However, for `Vec::::new` + // where the allocator param `A` has a default we will *not* infer. But + // for effect params this is a different story: if the user has not written + // anything explicit for the effect param, we always need to try to infer + // it before falling back to default, such that a `const fn` such as + // `needs_drop::<()>` can still be called in const contexts. (if we defaulted + // instead of inferred, typeck would error) + if tcx.has_attr(param.def_id, sym::rustc_host) { + return self.fcx.var_for_effect(param); + } else if !infer_args { + return tcx + .const_param_default(param.def_id) + .instantiate(tcx, args.unwrap()) + .into(); + } } + + self.fcx.var_for_def(self.span, param) } } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 7707cc6de54..6f0d8ca774f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -20,7 +20,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; use rustc_span::symbol::Ident; -use rustc_span::{self, Span, DUMMY_SP}; +use rustc_span::{self, sym, Span, DUMMY_SP}; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; use std::cell::{Cell, RefCell}; @@ -266,7 +266,11 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { param: Option<&ty::GenericParamDef>, span: Span, ) -> Const<'tcx> { + // FIXME ideally this shouldn't use unwrap match param { + Some(param) if self.tcx.has_attr(param.def_id, sym::rustc_host) => { + self.var_for_effect(param).as_const().unwrap() + } Some(param) => self.var_for_def(span, param).as_const().unwrap(), None => self.next_const_var( ty, diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 9d7a9fefd08..99bd296d0d5 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -522,6 +522,17 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } } } + ty::ConstKind::Infer(InferConst::EffectVar(vid)) => { + match self.infcx.probe_effect_var(vid) { + Some(value) => return self.fold_const(value.as_const(self.infcx.tcx)), + None => { + return self.canonicalize_const_var( + CanonicalVarInfo { kind: CanonicalVarKind::Effect }, + ct, + ); + } + } + } ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("encountered a fresh const during canonicalization") } @@ -690,7 +701,8 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { .iter() .map(|v| CanonicalVarInfo { kind: match v.kind { - CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => { + CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) + | CanonicalVarKind::Effect => { return *v; } CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => { diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 8ca2e403043..41787ee2942 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -151,7 +151,11 @@ impl<'tcx> InferCtxt<'tcx> { universe_map(ui), ) .into(), - + CanonicalVarKind::Effect => { + let vid = self.inner.borrow_mut().effect_unification_table().new_key(None); + ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid), self.tcx.types.bool) + .into() + } CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound }; diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index ddc8e7e50eb..377c414456d 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -30,7 +30,7 @@ use super::{DefineOpaqueTypes, InferCtxt, TypeTrace}; use crate::infer::generalize::{self, CombineDelegate, Generalization}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::infer::canonical::OriginalQueryValues; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; +use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; @@ -91,7 +91,7 @@ impl<'tcx> InferCtxt<'tcx> { .borrow_mut() .float_unification_table() .unify_var_var(a_id, b_id) - .map_err(|e| float_unification_error(relation.a_is_expected(), e))?; + .map_err(|e| float_unification_error(a_is_expected, e))?; Ok(a) } (&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => { @@ -210,10 +210,30 @@ impl<'tcx> InferCtxt<'tcx> { return Ok(a); } + ( + ty::ConstKind::Infer(InferConst::EffectVar(a_vid)), + ty::ConstKind::Infer(InferConst::EffectVar(b_vid)), + ) => { + self.inner + .borrow_mut() + .effect_unification_table() + .unify_var_var(a_vid, b_vid) + .map_err(|a| effect_unification_error(self.tcx, relation.a_is_expected(), a))?; + return Ok(a); + } + // All other cases of inference with other variables are errors. - (ty::ConstKind::Infer(InferConst::Var(_)), ty::ConstKind::Infer(_)) - | (ty::ConstKind::Infer(_), ty::ConstKind::Infer(InferConst::Var(_))) => { - bug!("tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var)") + ( + ty::ConstKind::Infer(InferConst::Var(_) | InferConst::EffectVar(_)), + ty::ConstKind::Infer(_), + ) + | ( + ty::ConstKind::Infer(_), + ty::ConstKind::Infer(InferConst::Var(_) | InferConst::EffectVar(_)), + ) => { + bug!( + "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}" + ) } (ty::ConstKind::Infer(InferConst::Var(vid)), _) => { @@ -223,6 +243,23 @@ impl<'tcx> InferCtxt<'tcx> { (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { return self.unify_const_variable(vid, a, relation.param_env()); } + + (ty::ConstKind::Infer(InferConst::EffectVar(vid)), _) => { + return self.unify_effect_variable( + relation.a_is_expected(), + vid, + EffectVarValue::Const(b), + ); + } + + (_, ty::ConstKind::Infer(InferConst::EffectVar(vid))) => { + return self.unify_effect_variable( + !relation.a_is_expected(), + vid, + EffectVarValue::Const(a), + ); + } + (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) if self.tcx.features().generic_const_exprs || self.next_trait_solver() => { @@ -340,6 +377,20 @@ impl<'tcx> InferCtxt<'tcx> { .map_err(|e| float_unification_error(vid_is_expected, e))?; Ok(Ty::new_float(self.tcx, val)) } + + fn unify_effect_variable( + &self, + vid_is_expected: bool, + vid: ty::EffectVid<'tcx>, + val: EffectVarValue<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { + self.inner + .borrow_mut() + .effect_unification_table() + .unify_var_value(vid, Some(val)) + .map_err(|e| effect_unification_error(self.tcx, vid_is_expected, e))?; + Ok(val.as_const(self.tcx)) + } } impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { @@ -493,3 +544,11 @@ fn float_unification_error<'tcx>( let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v; TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b)) } + +fn effect_unification_error<'tcx>( + tcx: TyCtxt<'tcx>, + a_is_expected: bool, + (a, b): (EffectVarValue<'tcx>, EffectVarValue<'tcx>), +) -> TypeError<'tcx> { + TypeError::ConstMismatch(ExpectedFound::new(a_is_expected, a.as_const(tcx), b.as_const(tcx))) +} diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 689945d644c..0596ce373cf 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -156,6 +156,21 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { .known(); self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty()) } + ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => { + let opt_ct = self + .infcx + .inner + .borrow_mut() + .effect_unification_table() + .probe_value(v) + .map(|effect| effect.as_const(self.infcx.tcx)); + self.freshen_const( + opt_ct, + ty::InferConst::EffectVar(v), + ty::InferConst::Fresh, + ct.ty(), + ) + } ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => { if i >= self.const_freshen_count { bug!( diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs index cf674d5dda6..dd7f8d35441 100644 --- a/compiler/rustc_infer/src/infer/generalize.rs +++ b/compiler/rustc_infer/src/infer/generalize.rs @@ -403,6 +403,7 @@ where } } } + ty::ConstKind::Infer(InferConst::EffectVar(_)) => Ok(c), // FIXME: remove this branch once `structurally_relate_consts` is fully // structural. ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index aaabf1482e2..b31046c2d32 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -21,7 +21,7 @@ use rustc_data_structures::unify as ut; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; +use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; @@ -33,13 +33,14 @@ use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt}; -use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid}; +use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid}; use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef}; use rustc_span::symbol::Symbol; -use rustc_span::Span; +use rustc_span::{sym, Span}; use std::cell::{Cell, RefCell}; use std::fmt; +use std::marker::PhantomData; use self::combine::CombineFields; use self::error_reporting::TypeErrCtxt; @@ -115,6 +116,9 @@ pub struct InferCtxtInner<'tcx> { /// Map from floating variable to the kind of float it represents. float_unification_storage: ut::UnificationTableStorage, + /// Map from effect variable to the effect param it represents. + effect_unification_storage: ut::UnificationTableStorage>, + /// Tracks the set of region variables and the constraints between them. /// /// This is initially `Some(_)` but when @@ -172,6 +176,7 @@ impl<'tcx> InferCtxtInner<'tcx> { const_unification_storage: ut::UnificationTableStorage::new(), int_unification_storage: ut::UnificationTableStorage::new(), float_unification_storage: ut::UnificationTableStorage::new(), + effect_unification_storage: ut::UnificationTableStorage::new(), region_constraint_storage: Some(RegionConstraintStorage::new()), region_obligations: vec![], opaque_type_storage: Default::default(), @@ -223,6 +228,10 @@ impl<'tcx> InferCtxtInner<'tcx> { self.const_unification_storage.with_log(&mut self.undo_log) } + fn effect_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::EffectVid<'tcx>> { + self.effect_unification_storage.with_log(&mut self.undo_log) + } + #[inline] pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'_, 'tcx> { self.region_constraint_storage @@ -356,6 +365,7 @@ impl<'tcx> ty::InferCtxtLike> for InferCtxt<'tcx> { Err(universe) => Some(universe), Ok(_) => None, }, + EffectVar(_) => None, Fresh(_) => None, } } @@ -777,6 +787,19 @@ impl<'tcx> InferCtxt<'tcx> { vars } + pub fn unsolved_effects(&self) -> Vec> { + let mut inner = self.inner.borrow_mut(); + let mut table = inner.effect_unification_table(); + + (0..table.len()) + .map(|i| ty::EffectVid { index: i as u32, phantom: PhantomData }) + .filter(|&vid| table.probe_value(vid).is_none()) + .map(|v| { + ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v), self.tcx.types.bool) + }) + .collect() + } + fn combine_fields<'a>( &'a self, trace: TypeTrace<'tcx>, @@ -1159,6 +1182,10 @@ impl<'tcx> InferCtxt<'tcx> { Ty::new_var(self.tcx, ty_var_id).into() } GenericParamDefKind::Const { .. } => { + // todo what about using effect var here + if self.tcx.has_attr(param.def_id, sym::rustc_host) { + return self.var_for_effect(param); + } let origin = ConstVariableOrigin { kind: ConstVariableOriginKind::ConstParameterDefinition( param.name, @@ -1184,6 +1211,17 @@ impl<'tcx> InferCtxt<'tcx> { } } + pub fn var_for_effect(&self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { + let effect_vid = self.inner.borrow_mut().effect_unification_table().new_key(None); + let ty = self + .tcx + .type_of(param.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic"); + debug_assert_eq!(self.tcx.types.bool, ty); + ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid), ty).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_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> { @@ -1369,6 +1407,10 @@ impl<'tcx> InferCtxt<'tcx> { } } + pub fn probe_effect_var(&self, vid: EffectVid<'tcx>) -> Option> { + self.inner.borrow_mut().effect_unification_table().probe_value(vid) + } + /// Attempts to resolve all type/region/const variables in /// `value`. Region inference must have been run already (e.g., /// by calling `resolve_regions_and_report_errors`). If some @@ -1649,6 +1691,14 @@ impl<'tcx> InferCtxt<'tcx> { ConstVariableValue::Known { .. } => true, } } + + TyOrConstInferVar::Effect(v) => { + // If `probe_value` returns `Some`, it never equals + // `ty::ConstKind::Infer(ty::InferConst::Effect(v))`. + // + // Not `inlined_probe_value(v)` because this call site is colder. + self.probe_effect_var(v).is_some() + } } } } @@ -1720,6 +1770,8 @@ pub enum TyOrConstInferVar<'tcx> { /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`. Const(ConstVid<'tcx>), + /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::EffectVar(_))`. + Effect(EffectVid<'tcx>), } impl<'tcx> TyOrConstInferVar<'tcx> { @@ -1750,6 +1802,7 @@ impl<'tcx> TyOrConstInferVar<'tcx> { fn maybe_from_const(ct: ty::Const<'tcx>) -> Option { match ct.kind() { ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)), + ty::ConstKind::Infer(InferConst::EffectVar(v)) => Some(TyOrConstInferVar::Effect(v)), _ => None, } } @@ -1793,17 +1846,24 @@ impl<'a, 'tcx> TypeFolder> for ShallowResolver<'a, 'tcx> { } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() { - self.infcx + match ct.kind() { + ty::ConstKind::Infer(InferConst::Var(vid)) => self + .infcx .inner .borrow_mut() .const_unification_table() .probe_value(vid) .val .known() - .unwrap_or(ct) - } else { - ct + .unwrap_or(ct), + ty::ConstKind::Infer(InferConst::EffectVar(vid)) => self + .infcx + .inner + .borrow_mut() + .effect_unification_table() + .probe_value(vid) + .map_or(ct, |val| val.as_const(self.infcx.tcx)), + _ => ct, } } } diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 25d06b21ec8..79144b3e643 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -24,6 +24,7 @@ pub(crate) enum UndoLog<'tcx> { ConstUnificationTable(sv::UndoLog>>), IntUnificationTable(sv::UndoLog>), FloatUnificationTable(sv::UndoLog>), + EffectUnificationTable(sv::UndoLog>>), RegionConstraintCollector(region_constraints::UndoLog<'tcx>), RegionUnificationTable(sv::UndoLog>>), ProjectionCache(traits::UndoLog<'tcx>), @@ -55,6 +56,7 @@ impl_from! { IntUnificationTable(sv::UndoLog>), FloatUnificationTable(sv::UndoLog>), + EffectUnificationTable(sv::UndoLog>>), ConstUnificationTable(sv::UndoLog>>), @@ -71,6 +73,7 @@ impl<'tcx> Rollback> for InferCtxtInner<'tcx> { UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo), UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo), UndoLog::FloatUnificationTable(undo) => self.float_unification_storage.reverse(undo), + UndoLog::EffectUnificationTable(undo) => self.effect_unification_storage.reverse(undo), UndoLog::RegionConstraintCollector(undo) => { self.region_constraint_storage.as_mut().unwrap().reverse(undo) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4f4351633a2..7eae164ad3d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -873,14 +873,14 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::AssocConst | DefKind::Macro(_) | DefKind::Field - | DefKind::Impl { .. } => true, + | DefKind::Impl { .. } + | DefKind::ConstParam => true, // Tools may want to be able to detect their tool lints on // closures from upstream crates, too. This is used by // https://github.com/model-checking/kani and is not a performance // or maintenance issue for us. DefKind::Closure => true, DefKind::TyParam - | DefKind::ConstParam | DefKind::Ctor(..) | DefKind::ExternCrate | DefKind::Use diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 81823118ab8..af9ca6b60c7 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -173,6 +173,7 @@ impl<'tcx> CanonicalVarInfo<'tcx> { CanonicalVarKind::PlaceholderRegion(..) => false, CanonicalVarKind::Const(..) => true, CanonicalVarKind::PlaceholderConst(_, _) => false, + CanonicalVarKind::Effect => true, } } @@ -182,7 +183,8 @@ impl<'tcx> CanonicalVarInfo<'tcx> { CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) | CanonicalVarKind::Const(_, _) - | CanonicalVarKind::PlaceholderConst(_, _) => false, + | CanonicalVarKind::PlaceholderConst(_, _) + | CanonicalVarKind::Effect => false, } } @@ -190,7 +192,8 @@ impl<'tcx> CanonicalVarInfo<'tcx> { match self.kind { CanonicalVarKind::Ty(_) | CanonicalVarKind::Region(_) - | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"), + | CanonicalVarKind::Const(_, _) + | CanonicalVarKind::Effect => bug!("expected placeholder: {self:?}"), CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(), CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(), @@ -222,6 +225,9 @@ pub enum CanonicalVarKind<'tcx> { /// Some kind of const inference variable. Const(ty::UniverseIndex, Ty<'tcx>), + /// Effect variable `'?E`. + Effect, + /// A "placeholder" that represents "any const". PlaceholderConst(ty::PlaceholderConst<'tcx>, Ty<'tcx>), } @@ -229,11 +235,11 @@ pub enum CanonicalVarKind<'tcx> { impl<'tcx> CanonicalVarKind<'tcx> { pub fn universe(self) -> ty::UniverseIndex { match self { - CanonicalVarKind::Ty(kind) => match kind { - CanonicalTyVarKind::General(ui) => ui, - CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT, - }, - + CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui, + CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => { + ty::UniverseIndex::ROOT + } + CanonicalVarKind::Effect => ty::UniverseIndex::ROOT, CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe, CanonicalVarKind::Region(ui) => ui, CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe, @@ -248,15 +254,14 @@ impl<'tcx> CanonicalVarKind<'tcx> { /// the updated universe is not the root. pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> { match self { - CanonicalVarKind::Ty(kind) => match kind { - CanonicalTyVarKind::General(_) => { - CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) - } - CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => { - assert_eq!(ui, ty::UniverseIndex::ROOT); - CanonicalVarKind::Ty(kind) - } - }, + CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => { + CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) + } + CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) + | CanonicalVarKind::Effect => { + assert_eq!(ui, ty::UniverseIndex::ROOT); + self + } CanonicalVarKind::PlaceholderTy(placeholder) => { CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder }) } @@ -443,6 +448,14 @@ impl<'tcx> CanonicalVarValues<'tcx> { }; ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into() } + // todo eh? + CanonicalVarKind::Effect => ty::Const::new_bound( + tcx, + ty::INNERMOST, + ty::BoundVar::from_usize(i), + tcx.types.bool, + ) + .into(), CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => ty::Const::new_bound( tcx, diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 85fb9214d9d..7ca9647590a 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -188,3 +188,53 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { }) } } + +/// values for the effect inference variable +#[derive(Clone, Copy, Debug)] +pub enum EffectVarValue<'tcx> { + /// The host effect is on, enabling access to syscalls, filesystem access, etc. + Host, + /// The host effect is off. Execution is restricted to const operations only. + NoHost, + Const(ty::Const<'tcx>), +} + +impl<'tcx> EffectVarValue<'tcx> { + pub fn as_const(self, tcx: TyCtxt<'tcx>) -> ty::Const<'tcx> { + match self { + EffectVarValue::Host => tcx.consts.true_, + EffectVarValue::NoHost => tcx.consts.false_, + EffectVarValue::Const(c) => c, + } + } +} + +impl<'tcx> UnifyValue for EffectVarValue<'tcx> { + type Error = (EffectVarValue<'tcx>, EffectVarValue<'tcx>); + fn unify_values(value1: &Self, value2: &Self) -> Result { + match (value1, value2) { + (EffectVarValue::Host, EffectVarValue::Host) => Ok(EffectVarValue::Host), + (EffectVarValue::NoHost, EffectVarValue::NoHost) => Ok(EffectVarValue::NoHost), + (EffectVarValue::NoHost | EffectVarValue::Host, _) + | (_, EffectVarValue::NoHost | EffectVarValue::Host) => Err((*value1, *value2)), + (EffectVarValue::Const(_), EffectVarValue::Const(_)) => { + bug!("equating two const variables, both of which have known values") + } + } + } +} + +impl<'tcx> UnifyKey for ty::EffectVid<'tcx> { + type Value = Option>; + #[inline] + fn index(&self) -> u32 { + self.index + } + #[inline] + fn from_index(i: u32) -> Self { + ty::EffectVid { index: i, phantom: PhantomData } + } + fn tag() -> &'static str { + "EffectVid" + } +} diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index db4a15fbee5..17fbbd7c6b7 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -55,6 +55,11 @@ static_assert_size!(super::ConstKind<'_>, 32); pub enum InferConst<'tcx> { /// Infer the value of the const. Var(ty::ConstVid<'tcx>), + /// Infer the value of the effect. + /// + /// For why this is separate from the `Var` variant above, see the + /// documentation on `EffectVid`. + EffectVar(ty::EffectVid<'tcx>), /// A fresh const variable. See `infer::freshen` for more details. Fresh(u32), } @@ -62,7 +67,9 @@ pub enum InferConst<'tcx> { impl HashStable for InferConst<'_> { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { match self { - InferConst::Var(_) => panic!("const variables should not be hashed: {self:?}"), + InferConst::Var(_) | InferConst::EffectVar(_) => { + panic!("const variables should not be hashed: {self:?}") + } InferConst::Fresh(i) => i.hash_stable(hcx, hasher), } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index bbd4a623330..3cafd9a8da9 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -324,7 +324,9 @@ impl FlagComputation { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); match infer { InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH), - InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER), + InferConst::Var(_) | InferConst::EffectVar(_) => { + self.add_flags(TypeFlags::HAS_CT_INFER) + } } } ty::ConstKind::Bound(debruijn, _) => { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1fdc4f7500f..99b697d0ea5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -98,9 +98,9 @@ pub use self::sty::BoundRegionKind::*; pub use self::sty::{ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, ConstKind, ConstVid, - EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, - FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs, InlineConstArgsParts, - ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, + EarlyBoundRegion, EffectVid, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, + FnSig, FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs, + InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, }; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index f979ddd00fa..e2e1d520548 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -138,6 +138,12 @@ impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> { } } +impl fmt::Debug for ty::EffectVid<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "?{}e", self.index) + } +} + impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths!(fmt::Display::fmt(self, f)) @@ -253,6 +259,7 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { InferConst::Var(var) => write!(f, "{var:?}"), + InferConst::EffectVar(var) => write!(f, "{var:?}"), InferConst::Fresh(var) => write!(f, "Fresh({var:?})"), } } @@ -267,6 +274,7 @@ impl<'tcx> DebugWithInfcx> for ty::InferConst<'tcx> { None => write!(f, "{:?}", this.data), Some(universe) => match *this.data { Var(vid) => write!(f, "?{}_{}c", vid.index, universe.index()), + EffectVar(vid) => write!(f, "?{}_{}e", vid.index, universe.index()), Fresh(_) => { unreachable!() } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 0291cdd6c57..b8627338d4c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1577,6 +1577,20 @@ pub struct ConstVid<'tcx> { pub phantom: PhantomData<&'tcx ()>, } +/// An **effect** **v**ariable **ID**. +/// +/// Handling effect infer variables happens separately from const infer variables +/// because we do not want to reuse any of the const infer machinery. If we try to +/// relate an effect variable with a normal one, we would ICE, which can catch bugs +/// where we are not correctly using the effect var for an effect param. Fallback +/// is also implemented on top of having separate effect and normal const variables. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(TyEncodable, TyDecodable)] +pub struct EffectVid<'tcx> { + pub index: u32, + pub phantom: PhantomData<&'tcx ()>, +} + rustc_index::newtype_index! { /// A **region** (lifetime) **v**ariable **ID**. #[derive(HashStable)] diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index a9d182abfb7..77c0f9f090c 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -365,6 +365,9 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { // FIXME: we should fold this ty eventually CanonicalVarKind::Const(ui, c.ty()) } + ty::ConstKind::Infer(ty::InferConst::EffectVar(_)) => { + bug!("effect var has no universe") + } ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => { bug!("fresh var during canonicalization: {c:?}") } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs new file mode 100644 index 00000000000..855bbb2e992 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/fallback.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(const_trait_impl, effects)] + +pub const fn owo() {} + +fn main() { + let _ = owo; +} From 9654d5ceaf3c0e916bcc99c2865d374595becc54 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 11 Sep 2023 13:18:36 +0000 Subject: [PATCH 2/2] add `is_host_effect` to `GenericParamDefKind::Const` and address review --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 2 +- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../rustc_hir_analysis/src/collect/generics_of.rs | 5 ++++- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 11 +++++++---- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 11 +++++++---- compiler/rustc_infer/src/infer/combine.rs | 8 ++++---- compiler/rustc_infer/src/infer/mod.rs | 7 +++---- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++-- compiler/rustc_middle/src/infer/canonical.rs | 1 - compiler/rustc_middle/src/ty/generics.rs | 6 +++--- compiler/rustc_privacy/src/lib.rs | 2 +- compiler/rustc_smir/src/rustc_smir/mod.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- 13 files changed, 35 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 90f64e18632..acfd8dcb112 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -523,7 +523,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Ty::new_misc_error(tcx).into() } } - GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Const { has_default, .. } => { let ty = tcx .at(self.span) .type_of(param.def_id) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f5beefc47f3..b97e0a80fe6 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1255,7 +1255,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id let is_our_default = |def: &ty::GenericParamDef| match def.kind { GenericParamDefKind::Type { has_default, .. } - | GenericParamDefKind::Const { has_default } => { + | GenericParamDefKind::Const { has_default, .. } => { has_default && def.index >= generics.parent_count as u32 } GenericParamDefKind::Lifetime => unreachable!(), diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 4842008279a..3d60c57b9d5 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -328,7 +328,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { name: param.name.ident().name, def_id: param.def_id.to_def_id(), pure_wrt_drop: param.pure_wrt_drop, - kind: ty::GenericParamDefKind::Const { has_default: default.is_some() }, + kind: ty::GenericParamDefKind::Const { + has_default: default.is_some(), + is_host_effect: is_host_param, + }, }) } })); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 694f3f67bab..c94cfde0670 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1295,10 +1295,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { self.fcx.ty_infer(Some(param), inf.span).into() } - (&GenericParamDefKind::Const { has_default }, GenericArg::Infer(inf)) => { + ( + &GenericParamDefKind::Const { has_default, is_host_effect }, + GenericArg::Infer(inf), + ) => { let tcx = self.fcx.tcx(); - if has_default && tcx.has_attr(param.def_id, sym::rustc_host) { + if has_default && is_host_effect { self.fcx.var_for_effect(param) } else { self.fcx @@ -1341,7 +1344,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.fcx.var_for_def(self.span, param) } } - GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Const { has_default, is_host_effect } => { if has_default { // N.B. this is a bit of a hack. `infer_args` is passed depending on // whether the user has provided generic args. E.g. for `Vec::new` @@ -1352,7 +1355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // it before falling back to default, such that a `const fn` such as // `needs_drop::<()>` can still be called in const contexts. (if we defaulted // instead of inferred, typeck would error) - if tcx.has_attr(param.def_id, sym::rustc_host) { + if is_host_effect { return self.fcx.var_for_effect(param); } else if !infer_args { return tcx diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 6f0d8ca774f..4237b4488ca 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -20,7 +20,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; use rustc_span::symbol::Ident; -use rustc_span::{self, sym, Span, DUMMY_SP}; +use rustc_span::{self, Span, DUMMY_SP}; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; use std::cell::{Cell, RefCell}; @@ -268,9 +268,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { ) -> Const<'tcx> { // FIXME ideally this shouldn't use unwrap match param { - Some(param) if self.tcx.has_attr(param.def_id, sym::rustc_host) => { - self.var_for_effect(param).as_const().unwrap() - } + Some( + param @ ty::GenericParamDef { + kind: ty::GenericParamDefKind::Const { is_host_effect: true, .. }, + .. + }, + ) => self.var_for_effect(param).as_const().unwrap(), Some(param) => self.var_for_def(span, param).as_const().unwrap(), None => self.next_const_var( ty, diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 377c414456d..ee13eb0271e 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -546,9 +546,9 @@ fn float_unification_error<'tcx>( } fn effect_unification_error<'tcx>( - tcx: TyCtxt<'tcx>, - a_is_expected: bool, - (a, b): (EffectVarValue<'tcx>, EffectVarValue<'tcx>), + _tcx: TyCtxt<'tcx>, + _a_is_expected: bool, + (_a, _b): (EffectVarValue<'tcx>, EffectVarValue<'tcx>), ) -> TypeError<'tcx> { - TypeError::ConstMismatch(ExpectedFound::new(a_is_expected, a.as_const(tcx), b.as_const(tcx))) + bug!("unexpected effect unification error") } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b31046c2d32..f637d509400 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -36,7 +36,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtx use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid}; use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef}; use rustc_span::symbol::Symbol; -use rustc_span::{sym, Span}; +use rustc_span::Span; use std::cell::{Cell, RefCell}; use std::fmt; @@ -1181,9 +1181,8 @@ impl<'tcx> InferCtxt<'tcx> { Ty::new_var(self.tcx, ty_var_id).into() } - GenericParamDefKind::Const { .. } => { - // todo what about using effect var here - if self.tcx.has_attr(param.def_id, sym::rustc_host) { + GenericParamDefKind::Const { is_host_effect, .. } => { + if is_host_effect { return self.var_for_effect(param); } let origin = ConstVariableOrigin { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7eae164ad3d..4f4351633a2 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -873,14 +873,14 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::AssocConst | DefKind::Macro(_) | DefKind::Field - | DefKind::Impl { .. } - | DefKind::ConstParam => true, + | DefKind::Impl { .. } => true, // Tools may want to be able to detect their tool lints on // closures from upstream crates, too. This is used by // https://github.com/model-checking/kani and is not a performance // or maintenance issue for us. DefKind::Closure => true, DefKind::TyParam + | DefKind::ConstParam | DefKind::Ctor(..) | DefKind::ExternCrate | DefKind::Use diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index af9ca6b60c7..e1db8f810a7 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -448,7 +448,6 @@ impl<'tcx> CanonicalVarValues<'tcx> { }; ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into() } - // todo eh? CanonicalVarKind::Effect => ty::Const::new_bound( tcx, ty::INNERMOST, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 70a35f137d8..ceac21cf6ea 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -12,7 +12,7 @@ use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamT pub enum GenericParamDefKind { Lifetime, Type { has_default: bool, synthetic: bool }, - Const { has_default: bool }, + Const { has_default: bool, is_host_effect: bool }, } impl GenericParamDefKind { @@ -87,7 +87,7 @@ impl GenericParamDef { GenericParamDefKind::Type { has_default, .. } if has_default => { Some(tcx.type_of(self.def_id).map_bound(|t| t.into())) } - GenericParamDefKind::Const { has_default } if has_default => { + GenericParamDefKind::Const { has_default, .. } if has_default => { Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into())) } _ => None, @@ -187,7 +187,7 @@ impl<'tcx> Generics { GenericParamDefKind::Type { has_default, .. } => { own_defaults.types += has_default as usize; } - GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Const { has_default, .. } => { own_defaults.consts += has_default as usize; } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 906a36cdb25..8f9b6f7fe03 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -836,7 +836,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity()); } } - GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Const { has_default, .. } => { self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity()); if has_default { self.visit( diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 822a6e48658..65d108f7633 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1242,7 +1242,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { ty::GenericParamDefKind::Type { has_default, synthetic } => { GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic } } - ty::GenericParamDefKind::Const { has_default } => { + ty::GenericParamDefKind::Const { has_default, is_host_effect: _ } => { GenericParamDefKind::Const { has_default: *has_default } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b584c32a4c7..cbcb8fd99d8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -541,7 +541,7 @@ fn clean_generic_param_def<'tcx>( }, ) } - ty::GenericParamDefKind::Const { has_default } => ( + ty::GenericParamDefKind::Const { has_default, .. } => ( def.name, GenericParamDefKind::Const { ty: Box::new(clean_middle_ty(