diff options
| author | bors <bors@rust-lang.org> | 2023-01-15 15:07:27 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-01-15 15:07:27 +0000 |
| commit | ae4d89dfb51535c1c43052ef848564bd2323c9ca (patch) | |
| tree | e58d5b1bef2947d2d676b2e996992f538ef0596a /compiler/rustc_trait_selection/src/solve | |
| parent | fc11ee02ee91b32e23684cd478bca80fe5323b47 (diff) | |
| parent | 1de196fef308c236aee8804c7b452ad5f5bbaf88 (diff) | |
| download | rust-ae4d89dfb51535c1c43052ef848564bd2323c9ca.tar.gz rust-ae4d89dfb51535c1c43052ef848564bd2323c9ca.zip | |
Auto merge of #106742 - compiler-errors:new-solver-make-it-not-ice, r=lcnr
Implement some FIXME methods in the new trait solver Implement just enough of the solver's response logic to make it not ICE. Also, fix a bug with `no_bound_vars` call failing due to canonical bound vars. r? `@lcnr`
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve')
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/assembly.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/cache.rs | 54 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/fulfill.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/mod.rs | 57 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/overflow.rs | 13 |
5 files changed, 98 insertions, 39 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index e9ddad11ff2..ba68da0686f 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -2,8 +2,8 @@ use super::infcx_ext::InferCtxtExt; use super::{ - fixme_instantiate_canonical_query_response, CanonicalGoal, CanonicalResponse, Certainty, - EvalCtxt, Goal, + instantiate_canonical_query_response, CanonicalGoal, CanonicalResponse, Certainty, EvalCtxt, + Goal, }; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -121,11 +121,8 @@ impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> { // canonical wrt the caller. for Candidate { source, result } in normalized_candidates { self.infcx.probe(|_| { - let candidate_certainty = fixme_instantiate_canonical_query_response( - &self.infcx, - &orig_values, - result, - ); + let candidate_certainty = + instantiate_canonical_query_response(&self.infcx, &orig_values, result); // FIXME: This is a bit scary if the `normalizes_to_goal` overflows. // diff --git a/compiler/rustc_trait_selection/src/solve/cache.rs b/compiler/rustc_trait_selection/src/solve/cache.rs index 993b7989066..f1ee73a5b85 100644 --- a/compiler/rustc_trait_selection/src/solve/cache.rs +++ b/compiler/rustc_trait_selection/src/solve/cache.rs @@ -9,11 +9,12 @@ //! FIXME(@lcnr): Write that section, feel free to ping me if you need help here //! before then or if I still haven't done that before January 2023. use super::overflow::OverflowData; -use super::CanonicalGoal; +use super::{CanonicalGoal, Certainty, MaybeCause, Response}; use super::{EvalCtxt, QueryResult}; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::TyCtxt; +use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues}; +use rustc_middle::ty::{self, TyCtxt}; use std::{cmp::Ordering, collections::hash_map::Entry}; #[derive(Debug, Clone)] @@ -111,11 +112,11 @@ impl<'tcx> EvalCtxt<'tcx> { // No entry, simply push this goal on the stack after dealing with overflow. Entry::Vacant(v) => { if self.overflow_data.has_overflow(cache.stack.len()) { - return Err(self.deal_with_overflow()); + return Err(self.deal_with_overflow(goal)); } v.insert(ProvisionalEntry { - response: fixme_response_yes_no_constraints(), + response: response_no_constraints(self.tcx, goal, Certainty::Yes), depth: cache.stack.len(), }); cache.stack.push(StackElem { goal, has_been_used: false }); @@ -150,7 +151,11 @@ impl<'tcx> EvalCtxt<'tcx> { { Err(entry.response) } else { - Err(fixme_response_maybe_no_constraints()) + Err(response_no_constraints( + self.tcx, + goal, + Certainty::Maybe(MaybeCause::Ambiguity), + )) } } } @@ -248,10 +253,39 @@ impl<'tcx> EvalCtxt<'tcx> { } } -fn fixme_response_yes_no_constraints<'tcx>() -> QueryResult<'tcx> { - unimplemented!() -} +pub(super) fn response_no_constraints<'tcx>( + tcx: TyCtxt<'tcx>, + goal: Canonical<'tcx, impl Sized>, + certainty: Certainty, +) -> QueryResult<'tcx> { + let var_values = goal + .variables + .iter() + .enumerate() + .map(|(i, info)| match info.kind { + CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => { + tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into())).into() + } + CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => { + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(i), + kind: ty::BrAnon(i as u32, None), + }; + tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() + } + CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => tcx + .mk_const(ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)), ty) + .into(), + }) + .collect(); -fn fixme_response_maybe_no_constraints<'tcx>() -> QueryResult<'tcx> { - unimplemented!() + Ok(Canonical { + max_universe: goal.max_universe, + variables: goal.variables, + value: Response { + var_values: CanonicalVarValues { var_values }, + external_constraints: Default::default(), + certainty, + }, + }) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index c014d682a9a..dfc2b5ed329 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -62,7 +62,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { let mut errors = Vec::new(); for i in 0.. { if !infcx.tcx.recursion_limit().value_within_limit(i) { - unimplemented!("overflow") + unimplemented!("overflowed on pending obligations: {:?}", self.obligations); } let mut has_changed = false; diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 7f5e3208f4e..042ba96b379 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -19,15 +19,19 @@ use std::mem; -use rustc_infer::infer::canonical::OriginalQueryValues; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse}; +use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::Obligation; +use rustc_middle::infer::canonical::Certainty as OldCertainty; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{RegionOutlivesPredicate, ToPredicate, TypeOutlivesPredicate}; use rustc_span::DUMMY_SP; +use crate::traits::ObligationCause; + +use self::cache::response_no_constraints; use self::infcx_ext::InferCtxtExt; mod assembly; @@ -119,7 +123,7 @@ pub enum MaybeCause { } /// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable, Default)] pub struct ExternalConstraints<'tcx> { // FIXME: implement this. regions: (), @@ -175,7 +179,7 @@ impl<'tcx> EvalCtxt<'tcx> { let canonical_response = self.evaluate_canonical_goal(canonical_goal)?; Ok(( true, // FIXME: check whether `var_values` are an identity substitution. - fixme_instantiate_canonical_query_response(infcx, &orig_values, canonical_response), + instantiate_canonical_query_response(infcx, &orig_values, canonical_response), )) } @@ -208,7 +212,8 @@ impl<'tcx> EvalCtxt<'tcx> { // of `PredicateKind` this is the case and it is and faster than instantiating and // recanonicalizing. let Goal { param_env, predicate } = canonical_goal.value; - if let Some(kind) = predicate.kind().no_bound_vars() { + + if let Some(kind) = predicate.kind().no_bound_vars_ignoring_escaping(self.tcx) { match kind { ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => self.compute_trait_goal( canonical_goal.unchecked_rebind(Goal { param_env, predicate }), @@ -234,7 +239,10 @@ impl<'tcx> EvalCtxt<'tcx> { | ty::PredicateKind::ConstEvaluatable(_) | ty::PredicateKind::ConstEquate(_, _) | ty::PredicateKind::TypeWellFormedFromEnv(_) - | ty::PredicateKind::Ambiguous => unimplemented!(), + | ty::PredicateKind::Ambiguous => { + // FIXME + response_no_constraints(self.tcx, canonical_goal, Certainty::Yes) + } } } else { let (infcx, goal, var_values) = @@ -248,16 +256,18 @@ impl<'tcx> EvalCtxt<'tcx> { fn compute_type_outlives_goal( &mut self, - _goal: CanonicalGoal<'tcx, TypeOutlivesPredicate<'tcx>>, + goal: CanonicalGoal<'tcx, TypeOutlivesPredicate<'tcx>>, ) -> QueryResult<'tcx> { - todo!() + // FIXME + response_no_constraints(self.tcx, goal, Certainty::Yes) } fn compute_region_outlives_goal( &mut self, - _goal: CanonicalGoal<'tcx, RegionOutlivesPredicate<'tcx>>, + goal: CanonicalGoal<'tcx, RegionOutlivesPredicate<'tcx>>, ) -> QueryResult<'tcx> { - todo!() + // FIXME + response_no_constraints(self.tcx, goal, Certainty::Yes) } } @@ -300,10 +310,27 @@ impl<'tcx> EvalCtxt<'tcx> { } } -fn fixme_instantiate_canonical_query_response<'tcx>( - _: &InferCtxt<'tcx>, - _: &OriginalQueryValues<'tcx>, - _: CanonicalResponse<'tcx>, +fn instantiate_canonical_query_response<'tcx>( + infcx: &InferCtxt<'tcx>, + original_values: &OriginalQueryValues<'tcx>, + response: CanonicalResponse<'tcx>, ) -> Certainty { - unimplemented!() + let Ok(InferOk { value, obligations }) = infcx + .instantiate_query_response_and_region_obligations( + &ObligationCause::dummy(), + ty::ParamEnv::empty(), + original_values, + &response.unchecked_map(|resp| QueryResponse { + var_values: resp.var_values, + region_constraints: QueryRegionConstraints::default(), + certainty: match resp.certainty { + Certainty::Yes => OldCertainty::Proven, + Certainty::Maybe(_) => OldCertainty::Ambiguous, + }, + opaque_types: resp.external_constraints.opaque_types, + value: resp.certainty, + }), + ) else { bug!(); }; + assert!(obligations.is_empty()); + value } diff --git a/compiler/rustc_trait_selection/src/solve/overflow.rs b/compiler/rustc_trait_selection/src/solve/overflow.rs index fdd6adb681b..8bbb9f63e78 100644 --- a/compiler/rustc_trait_selection/src/solve/overflow.rs +++ b/compiler/rustc_trait_selection/src/solve/overflow.rs @@ -1,7 +1,9 @@ +use rustc_infer::infer::canonical::Canonical; use rustc_infer::traits::query::NoSolution; use rustc_middle::ty::TyCtxt; use rustc_session::Limit; +use super::cache::response_no_constraints; use super::{Certainty, EvalCtxt, MaybeCause, QueryResult}; /// When detecting a solver overflow, we return ambiguity. Overflow can be @@ -49,9 +51,12 @@ impl OverflowData { } impl<'tcx> EvalCtxt<'tcx> { - pub(super) fn deal_with_overflow(&mut self) -> QueryResult<'tcx> { + pub(super) fn deal_with_overflow( + &mut self, + goal: Canonical<'tcx, impl Sized>, + ) -> QueryResult<'tcx> { self.overflow_data.deal_with_overflow(); - fixme_response_overflow_no_constraints() + response_no_constraints(self.tcx, goal, Certainty::Maybe(MaybeCause::Overflow)) } /// A `while`-loop which tracks overflow. @@ -74,7 +79,3 @@ impl<'tcx> EvalCtxt<'tcx> { Ok(Certainty::Maybe(MaybeCause::Overflow)) } } - -fn fixme_response_overflow_no_constraints<'tcx>() -> QueryResult<'tcx> { - unimplemented!() -} |
