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 {
|
fn associated_const_equality(self) -> bool {
|
||||||
self.associated_const_equality()
|
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 {
|
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::placeholder::BoundVarReplacer;
|
||||||
use crate::solve::inspect::{self, ProofTreeBuilder};
|
use crate::solve::inspect::{self, ProofTreeBuilder};
|
||||||
use crate::solve::search_graph::SearchGraph;
|
use crate::solve::search_graph::SearchGraph;
|
||||||
|
use crate::solve::ty::may_use_unstable_feature;
|
||||||
use crate::solve::{
|
use crate::solve::{
|
||||||
CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluation, GoalEvaluationKind,
|
CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluation, GoalEvaluationKind,
|
||||||
GoalSource, GoalStalledOn, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput,
|
GoalSource, GoalStalledOn, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput,
|
||||||
@@ -550,6 +551,9 @@ where
|
|||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||||
self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (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) => {
|
ty::PredicateKind::Subtype(predicate) => {
|
||||||
self.compute_subtype_goal(Goal { param_env, predicate })
|
self.compute_subtype_goal(Goal { param_env, predicate })
|
||||||
}
|
}
|
||||||
@@ -1177,6 +1181,14 @@ where
|
|||||||
) -> T {
|
) -> T {
|
||||||
BoundVarReplacer::replace_bound_vars(&**self.delegate, universes, t).0
|
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`
|
/// 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))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
fn compute_const_evaluatable_goal(
|
fn compute_const_evaluatable_goal(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ use rustc_infer::traits::{
|
|||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
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 thin_vec::{ThinVec, thin_vec};
|
||||||
use tracing::{debug, debug_span, instrument};
|
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::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt,
|
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 rustc_span::{Symbol, sym};
|
||||||
use tracing::{debug, instrument, trace};
|
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)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
|
||||||
match const_evaluatable::is_const_evaluatable(
|
match const_evaluatable::is_const_evaluatable(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
|
|||||||
@@ -285,3 +285,45 @@ pub trait InferCtxtLike: Sized {
|
|||||||
|
|
||||||
fn reset_opaque_types(&self);
|
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 coroutine_clone(self) -> bool;
|
||||||
|
|
||||||
fn associated_const_equality(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> {
|
pub trait DefId<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
|
||||||
|
|||||||
Reference in New Issue
Block a user