diff options
Diffstat (limited to 'compiler')
7 files changed, 113 insertions, 16 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index b67f8ded2a5..2badd66e346 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -9,8 +9,8 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{GenericPredicates, ToPredicate}; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; @@ -151,7 +151,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP trace!(?generics); // Collect the predicates that were written inline by the user on each - // type parameter (e.g., `<T: Foo>`). + // type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates + // for each const parameter. for param in ast_generics.params { match param.kind { // We already dealt with early bound lifetimes above. @@ -175,7 +176,19 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP trace!(?predicates); } GenericParamKind::Const { .. } => { - // Bounds on const parameters are currently not possible. + let name = param.name.ident().name; + let param_const = ty::ParamConst::new(index, name); + + let ct_ty = tcx.type_of(param.def_id.to_def_id()).subst_identity(); + + let ct = tcx.mk_const(param_const, ct_ty); + + let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( + ty::Clause::ConstArgHasType(ct, ct_ty), + )) + .to_predicate(tcx); + predicates.insert((predicate, param.span)); + index += 1; } } @@ -439,7 +452,9 @@ pub(super) fn explicit_predicates_of<'tcx>( let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let parent_def_id = tcx.hir().get_parent_item(hir_id); - if tcx.hir().opt_const_param_default_param_def_id(hir_id).is_some() { + if let Some(defaulted_param_def_id) = + tcx.hir().opt_const_param_default_param_def_id(hir_id) + { // In `generics_of` we set the generics' parent to be our parent's parent which means that // we lose out on the predicates of our actual parent if we dont return those predicates here. // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) @@ -452,7 +467,39 @@ pub(super) fn explicit_predicates_of<'tcx>( // // In the above code we want the anon const to have predicates in its param env for `T: Trait` // and we would be calling `explicit_predicates_of(Foo)` here - return tcx.explicit_predicates_of(parent_def_id); + let parent_preds = tcx.explicit_predicates_of(parent_def_id); + + // If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter + // will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution + // to #106994 is implemented. + let filtered_predicates = parent_preds + .predicates + .into_iter() + .filter(|(pred, _)| { + if let ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, _)) = + pred.kind().skip_binder() + { + match ct.kind() { + ty::ConstKind::Param(param_const) => { + let defaulted_param_idx = tcx + .generics_of(parent_def_id) + .param_def_id_to_index[&defaulted_param_def_id.to_def_id()]; + param_const.index < defaulted_param_idx + } + _ => bug!( + "`ConstArgHasType` in `predicates_of`\ + that isn't a `Param` const" + ), + } + } else { + true + } + }) + .cloned(); + return GenericPredicates { + parent: parent_preds.parent, + predicates: { tcx.arena.alloc_from_iter(filtered_predicates) }, + }; } let parent_def_kind = tcx.def_kind(parent_def_id); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 2562a1739f5..4741e4b095d 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -496,6 +496,16 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc ) .emit(); } + ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => { + // FIXME(min_specialization), FIXME(const_generics): + // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure + // about the actual rules that would be sound. Can't just always error here because otherwise + // std/core doesn't even compile as they have `const N: usize` in some specializing impls. + // + // While we do not support constructs like `<T, const N: T>` there is probably no risk of + // soundness bugs, but when we support generic const parameter types this will need to be + // revisited. + } _ => { tcx.sess .struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate)) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 64c7fafa713..58dfca75c65 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -159,9 +159,21 @@ where _region, ))) => ty.visit_with(self), ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => ControlFlow::Continue(()), + ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { + ct.visit_with(self)?; + ty.visit_with(self) + } ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self), ty::PredicateKind::WellFormed(arg) => arg.visit_with(self), - _ => bug!("unexpected predicate: {:?}", predicate), + + ty::PredicateKind::ObjectSafe(_) + | ty::PredicateKind::ClosureKind(_, _, _) + | ty::PredicateKind::Subtype(_) + | ty::PredicateKind::Coerce(_) + | ty::PredicateKind::ConstEquate(_, _) + | ty::PredicateKind::TypeWellFormedFromEnv(_) + | ty::PredicateKind::Ambiguous + | ty::PredicateKind::AliasEq(_, _) => bug!("unexpected predicate: {:?}", predicate), } } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 217851ba1d9..6890811fd04 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -25,7 +25,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::Obligation; use rustc_middle::infer::canonical::Certainty as OldCertainty; use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate, }; @@ -290,8 +290,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => { self.compute_region_outlives_goal(Goal { param_env, predicate }) } - ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => { - unimplemented!() + ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { + self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) }) } ty::PredicateKind::Subtype(predicate) => { self.compute_subtype_goal(Goal { param_env, predicate }) @@ -474,6 +474,16 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } } } + + #[instrument(level = "debug", skip(self), ret)] + fn compute_const_arg_has_type_goal( + &mut self, + goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>, + ) -> QueryResult<'tcx> { + let (ct, ty) = goal.predicate; + let nested_goals = self.infcx.eq(goal.param_env, ct.ty(), ty)?; + self.evaluate_all_and_make_canonical_response(nested_goals) + } } impl<'tcx> EvalCtxt<'_, 'tcx> { 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 02652200811..2511e9a955a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1283,9 +1283,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { "AliasEq predicate should never be the predicate cause of a SelectionError" ), - ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => { - // FIXME: don't know how selection error works so unsure when this is reachable (if it is) - unimplemented!() + ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { + self.tcx.sess.struct_span_err( + span, + &format!("the constant `{}` is not of type `{}`", ct, ty), + ) } } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 59be80236f8..deeed930e50 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -601,8 +601,18 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::AliasEq(..) => { bug!("AliasEq is only used for new solver") } - ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => { - unimplemented!() + ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { + match self + .selcx + .infcx + .at(&obligation.cause, obligation.param_env) + .eq(ct.ty(), ty) + { + Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), + Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError( + SelectionError::Unimplemented, + )), + } } }, } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2cfaaf1d376..e6fc9bb9239 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -993,8 +993,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bug!("AliasEq is only used for new solver") } ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), - ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => { - unimplemented!() + ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { + match self.infcx.at(&obligation.cause, obligation.param_env).eq(ct.ty(), ty) { + Ok(inf_ok) => self.evaluate_predicates_recursively( + previous_stack, + inf_ok.into_obligations(), + ), + Err(_) => Ok(EvaluatedToErr), + } } } }) |
