Add the core logic in old and new solvers
This commit is contained in:
@@ -833,6 +833,13 @@ impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_featu
|
||||
fn associated_const_equality(self) -> bool {
|
||||
self.associated_const_equality()
|
||||
}
|
||||
|
||||
fn feature_bound_holds_in_crate(self, symbol: Symbol) -> bool {
|
||||
// We don't consider feature bounds to hold in the crate when `staged_api` feature is
|
||||
// enabled, even if it is enabled through `#[feature]`.
|
||||
// This is to prevent accidentally leaking unstable APIs to stable.
|
||||
!self.staged_api() && self.enabled(symbol)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Span<TyCtxt<'tcx>> for Span {
|
||||
|
||||
@@ -22,6 +22,7 @@ use crate::delegate::SolverDelegate;
|
||||
use crate::placeholder::BoundVarReplacer;
|
||||
use crate::solve::inspect::{self, ProofTreeBuilder};
|
||||
use crate::solve::search_graph::SearchGraph;
|
||||
use crate::solve::ty::may_use_unstable_feature;
|
||||
use crate::solve::{
|
||||
CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluation, GoalEvaluationKind,
|
||||
GoalSource, GoalStalledOn, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput,
|
||||
@@ -550,6 +551,9 @@ where
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||
self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
|
||||
self.compute_unstable_feature_goal(param_env, symbol)
|
||||
}
|
||||
ty::PredicateKind::Subtype(predicate) => {
|
||||
self.compute_subtype_goal(Goal { param_env, predicate })
|
||||
}
|
||||
@@ -1177,6 +1181,14 @@ where
|
||||
) -> T {
|
||||
BoundVarReplacer::replace_bound_vars(&**self.delegate, universes, t).0
|
||||
}
|
||||
|
||||
pub(super) fn may_use_unstable_feature(
|
||||
&self,
|
||||
param_env: I::ParamEnv,
|
||||
symbol: I::Symbol,
|
||||
) -> bool {
|
||||
may_use_unstable_feature(&**self.delegate, param_env, symbol)
|
||||
}
|
||||
}
|
||||
|
||||
/// Eagerly replace aliases with inference variables, emitting `AliasRelate`
|
||||
|
||||
@@ -148,6 +148,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_unstable_feature_goal(
|
||||
&mut self,
|
||||
param_env: <I as Interner>::ParamEnv,
|
||||
symbol: <I as Interner>::Symbol,
|
||||
) -> QueryResult<I> {
|
||||
if self.may_use_unstable_feature(param_env, symbol) {
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
} else {
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Maybe(
|
||||
MaybeCause::Ambiguity,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn compute_const_evaluatable_goal(
|
||||
&mut self,
|
||||
|
||||
@@ -11,7 +11,9 @@ use rustc_infer::traits::{
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode};
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode, may_use_unstable_feature,
|
||||
};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
use tracing::{debug, debug_span, instrument};
|
||||
|
||||
@@ -767,6 +769,13 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
|
||||
if may_use_unstable_feature(self.selcx.infcx, obligation.param_env, symbol) {
|
||||
ProcessResult::Changed(Default::default())
|
||||
} else {
|
||||
ProcessResult::Unchanged
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{
|
||||
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt,
|
||||
TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate,
|
||||
TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate, may_use_unstable_feature,
|
||||
};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use tracing::{debug, instrument, trace};
|
||||
@@ -832,6 +832,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
|
||||
if may_use_unstable_feature(self.infcx, obligation.param_env, symbol) {
|
||||
Ok(EvaluatedToOk)
|
||||
} else {
|
||||
Ok(EvaluatedToAmbig)
|
||||
}
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
|
||||
match const_evaluatable::is_const_evaluatable(
|
||||
self.infcx,
|
||||
|
||||
@@ -285,3 +285,45 @@ pub trait InferCtxtLike: Sized {
|
||||
|
||||
fn reset_opaque_types(&self);
|
||||
}
|
||||
|
||||
pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
|
||||
infcx: &'a Infcx,
|
||||
param_env: I::ParamEnv,
|
||||
symbol: I::Symbol,
|
||||
) -> bool
|
||||
where
|
||||
Infcx: InferCtxtLike<Interner = I>,
|
||||
{
|
||||
// Iterate through all goals in param_env to find the one that has the same symbol.
|
||||
for pred in param_env.caller_bounds().iter() {
|
||||
if let ty::ClauseKind::UnstableFeature(sym) = pred.kind().skip_binder() {
|
||||
if sym == symbol {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// During codegen we must assume that all feature bounds hold as we may be
|
||||
// monomorphizing a body from an upstream crate which had an unstable feature
|
||||
// enabled that we do not.
|
||||
//
|
||||
// Coherence should already report overlap errors involving unstable impls
|
||||
// as the affected code would otherwise break when stabilizing this feature.
|
||||
// It is also easily possible to accidentally cause unsoundness this way as
|
||||
// we have to always enable unstable impls during codegen.
|
||||
//
|
||||
// Return ambiguity can also prevent people from writing code which depends on inference guidance
|
||||
// that might no longer work after the impl is stabilised,
|
||||
// tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
|
||||
//
|
||||
// Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
|
||||
// if we are in std/core even if there is a corresponding `feature` attribute on the crate.
|
||||
|
||||
if (infcx.typing_mode() == TypingMode::PostAnalysis)
|
||||
|| infcx.cx().features().feature_bound_holds_in_crate(symbol)
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,6 +630,8 @@ pub trait Features<I: Interner>: Copy {
|
||||
fn coroutine_clone(self) -> bool;
|
||||
|
||||
fn associated_const_equality(self) -> bool;
|
||||
|
||||
fn feature_bound_holds_in_crate(self, symbol: I::Symbol) -> bool;
|
||||
}
|
||||
|
||||
pub trait DefId<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
|
||||
|
||||
Reference in New Issue
Block a user