mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-30 19:49:36 +00:00 
			
		
		
		
	Fix failing tests and fill-in missing details
This commit is contained in:
		
							parent
							
								
									d24e8c1d38
								
							
						
					
					
						commit
						4a8bc8db38
					
				
					 36 changed files with 917 additions and 1431 deletions
				
			
		|  | @ -13,7 +13,7 @@ use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     Canonical, Goal, Interner, ProjectionTyExt, TraitEnvironment, Ty, TyBuilder, TyKind, |     Canonical, Goal, Interner, ProjectionTyExt, TraitEnvironment, Ty, TyBuilder, TyKind, | ||||||
|     db::HirDatabase, infer::unify::InferenceTable, |     db::HirDatabase, infer::unify::InferenceTable, next_solver::mapping::ChalkToNextSolver, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const AUTODEREF_RECURSION_LIMIT: usize = 20; | const AUTODEREF_RECURSION_LIMIT: usize = 20; | ||||||
|  | @ -98,7 +98,7 @@ impl<'table, 'db> Autoderef<'table, 'db> { | ||||||
|         explicit: bool, |         explicit: bool, | ||||||
|         use_receiver_trait: bool, |         use_receiver_trait: bool, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         let ty = table.resolve_ty_shallow(&ty); |         let ty = table.structurally_resolve_type(&ty); | ||||||
|         Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit, use_receiver_trait } |         Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit, use_receiver_trait } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -114,7 +114,7 @@ impl<'table, 'db> Autoderef<'table, 'db, usize> { | ||||||
|         explicit: bool, |         explicit: bool, | ||||||
|         use_receiver_trait: bool, |         use_receiver_trait: bool, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         let ty = table.resolve_ty_shallow(&ty); |         let ty = table.structurally_resolve_type(&ty); | ||||||
|         Autoderef { table, ty, at_start: true, steps: 0, explicit, use_receiver_trait } |         Autoderef { table, ty, at_start: true, steps: 0, explicit, use_receiver_trait } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -160,7 +160,7 @@ pub(crate) fn autoderef_step( | ||||||
|     use_receiver_trait: bool, |     use_receiver_trait: bool, | ||||||
| ) -> Option<(AutoderefKind, Ty)> { | ) -> Option<(AutoderefKind, Ty)> { | ||||||
|     if let Some(derefed) = builtin_deref(table.db, &ty, explicit) { |     if let Some(derefed) = builtin_deref(table.db, &ty, explicit) { | ||||||
|         Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed))) |         Some((AutoderefKind::Builtin, table.structurally_resolve_type(derefed))) | ||||||
|     } else { |     } else { | ||||||
|         Some((AutoderefKind::Overloaded, deref_by_trait(table, ty, use_receiver_trait)?)) |         Some((AutoderefKind::Overloaded, deref_by_trait(table, ty, use_receiver_trait)?)) | ||||||
|     } |     } | ||||||
|  | @ -187,7 +187,7 @@ pub(crate) fn deref_by_trait( | ||||||
|     use_receiver_trait: bool, |     use_receiver_trait: bool, | ||||||
| ) -> Option<Ty> { | ) -> Option<Ty> { | ||||||
|     let _p = tracing::info_span!("deref_by_trait").entered(); |     let _p = tracing::info_span!("deref_by_trait").entered(); | ||||||
|     if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() { |     if table.structurally_resolve_type(&ty).inference_var(Interner).is_some() { | ||||||
|         // don't try to deref unknown variables
 |         // don't try to deref unknown variables
 | ||||||
|         return None; |         return None; | ||||||
|     } |     } | ||||||
|  | @ -229,8 +229,8 @@ pub(crate) fn deref_by_trait( | ||||||
|         return None; |         return None; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     table.register_obligation(implements_goal); |     table.register_obligation(implements_goal.to_nextsolver(table.interner)); | ||||||
| 
 | 
 | ||||||
|     let result = table.normalize_projection_ty(projection); |     let result = table.normalize_projection_ty(projection); | ||||||
|     Some(table.resolve_ty_shallow(&result)) |     Some(table.structurally_resolve_type(&result)) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -245,10 +245,7 @@ impl TyExt for Ty { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { |     fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { | ||||||
|         match self.kind(Interner) { |         let handle_async_block_type_impl_trait = |def: DefWithBodyId| { | ||||||
|             TyKind::OpaqueType(opaque_ty_id, subst) => { |  | ||||||
|                 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { |  | ||||||
|                     ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => { |  | ||||||
|             let krate = def.module(db).krate(); |             let krate = def.module(db).krate(); | ||||||
|             if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) { |             if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) { | ||||||
|                 // This is only used by type walking.
 |                 // This is only used by type walking.
 | ||||||
|  | @ -265,6 +262,13 @@ impl TyExt for Ty { | ||||||
|             } else { |             } else { | ||||||
|                 None |                 None | ||||||
|             } |             } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         match self.kind(Interner) { | ||||||
|  |             TyKind::OpaqueType(opaque_ty_id, subst) => { | ||||||
|  |                 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { | ||||||
|  |                     ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => { | ||||||
|  |                         handle_async_block_type_impl_trait(def) | ||||||
|                     } |                     } | ||||||
|                     ImplTraitId::ReturnTypeImplTrait(func, idx) => { |                     ImplTraitId::ReturnTypeImplTrait(func, idx) => { | ||||||
|                         db.return_type_impl_traits(func).map(|it| { |                         db.return_type_impl_traits(func).map(|it| { | ||||||
|  | @ -299,8 +303,9 @@ impl TyExt for Ty { | ||||||
|                             data.substitute(Interner, &opaque_ty.substitution) |                             data.substitute(Interner, &opaque_ty.substitution) | ||||||
|                         }) |                         }) | ||||||
|                     } |                     } | ||||||
|                     // It always has an parameter for Future::Output type.
 |                     ImplTraitId::AsyncBlockTypeImplTrait(def, _) => { | ||||||
|                     ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(), |                         return handle_async_block_type_impl_trait(def); | ||||||
|  |                     } | ||||||
|                 }; |                 }; | ||||||
| 
 | 
 | ||||||
|                 predicates.map(|it| it.into_value_and_skipped_binders().0) |                 predicates.map(|it| it.into_value_and_skipped_binders().0) | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ use crate::{ | ||||||
|     next_solver::{ |     next_solver::{ | ||||||
|         Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, |         Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, | ||||||
|         ParamConst, SolverDefId, Ty, ValueConst, |         ParamConst, SolverDefId, Ty, ValueConst, | ||||||
|         mapping::{ChalkToNextSolver, convert_binder_to_early_binder}, |         mapping::{ChalkToNextSolver, NextSolverToChalk, convert_binder_to_early_binder}, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -145,7 +145,7 @@ pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option<u | ||||||
|                 SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), |                 SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), | ||||||
|                 _ => unreachable!(), |                 _ => unreachable!(), | ||||||
|             }; |             }; | ||||||
|             let subst = ChalkToNextSolver::from_nextsolver(unevaluated_const.args, interner); |             let subst = unevaluated_const.args.to_chalk(interner); | ||||||
|             let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); |             let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); | ||||||
|             try_const_usize(db, ec) |             try_const_usize(db, ec) | ||||||
|         } |         } | ||||||
|  | @ -168,7 +168,7 @@ pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option< | ||||||
|                 SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), |                 SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), | ||||||
|                 _ => unreachable!(), |                 _ => unreachable!(), | ||||||
|             }; |             }; | ||||||
|             let subst = ChalkToNextSolver::from_nextsolver(unevaluated_const.args, interner); |             let subst = unevaluated_const.args.to_chalk(interner); | ||||||
|             let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); |             let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); | ||||||
|             try_const_isize(db, &ec) |             try_const_isize(db, &ec) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -55,10 +55,9 @@ use stdx::{always, never}; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId, |     AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, ImplTraitId, ImplTraitIdx, | ||||||
|     ImplTraitIdx, InEnvironment, IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId, |     IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId, ParamLoweringMode, | ||||||
|     ParamLoweringMode, PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty, |     PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, | ||||||
|     TyBuilder, TyExt, |  | ||||||
|     db::HirDatabase, |     db::HirDatabase, | ||||||
|     fold_tys, |     fold_tys, | ||||||
|     generics::Generics, |     generics::Generics, | ||||||
|  | @ -70,6 +69,7 @@ use crate::{ | ||||||
|     }, |     }, | ||||||
|     lower::{ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic}, |     lower::{ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic}, | ||||||
|     mir::MirSpan, |     mir::MirSpan, | ||||||
|  |     next_solver::{self, mapping::ChalkToNextSolver}, | ||||||
|     static_lifetime, to_assoc_type_id, |     static_lifetime, to_assoc_type_id, | ||||||
|     traits::FnTrait, |     traits::FnTrait, | ||||||
|     utils::UnevaluatedConstEvaluatorFolder, |     utils::UnevaluatedConstEvaluatorFolder, | ||||||
|  | @ -182,13 +182,13 @@ impl BindingMode { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub(crate) struct InferOk<T> { | pub(crate) struct InferOk<'db, T> { | ||||||
|     value: T, |     value: T, | ||||||
|     goals: Vec<InEnvironment<Goal>>, |     goals: Vec<next_solver::Goal<'db, next_solver::Predicate<'db>>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<T> InferOk<T> { | impl<'db, T> InferOk<'db, T> { | ||||||
|     fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<U> { |     fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<'db, U> { | ||||||
|         InferOk { value: f(self.value), goals: self.goals } |         InferOk { value: f(self.value), goals: self.goals } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -203,7 +203,7 @@ pub enum InferenceTyDiagnosticSource { | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub(crate) struct TypeError; | pub(crate) struct TypeError; | ||||||
| pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>; | pub(crate) type InferResult<'db, T> = Result<InferOk<'db, T>, TypeError>; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, PartialEq, Eq, Clone)] | #[derive(Debug, PartialEq, Eq, Clone)] | ||||||
| pub enum InferenceDiagnostic { | pub enum InferenceDiagnostic { | ||||||
|  | @ -832,6 +832,7 @@ impl<'db> InferenceContext<'db> { | ||||||
|             coercion_casts, |             coercion_casts, | ||||||
|             diagnostics: _, |             diagnostics: _, | ||||||
|         } = &mut result; |         } = &mut result; | ||||||
|  |         table.resolve_obligations_as_possible(); | ||||||
|         table.fallback_if_possible(); |         table.fallback_if_possible(); | ||||||
| 
 | 
 | ||||||
|         // Comment from rustc:
 |         // Comment from rustc:
 | ||||||
|  | @ -1480,7 +1481,8 @@ impl<'db> InferenceContext<'db> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn push_obligation(&mut self, o: DomainGoal) { |     fn push_obligation(&mut self, o: DomainGoal) { | ||||||
|         self.table.register_obligation(o.cast(Interner)); |         let goal: crate::Goal = o.cast(Interner); | ||||||
|  |         self.table.register_obligation(goal.to_nextsolver(self.table.interner)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |     fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | ||||||
|  | @ -1746,7 +1748,7 @@ impl<'db> InferenceContext<'db> { | ||||||
| 
 | 
 | ||||||
|                     ty = self.table.insert_type_vars(ty); |                     ty = self.table.insert_type_vars(ty); | ||||||
|                     ty = self.table.normalize_associated_types_in(ty); |                     ty = self.table.normalize_associated_types_in(ty); | ||||||
|                     ty = self.table.resolve_ty_shallow(&ty); |                     ty = self.table.structurally_resolve_type(&ty); | ||||||
|                     if ty.is_unknown() { |                     if ty.is_unknown() { | ||||||
|                         return (self.err_ty(), None); |                         return (self.err_ty(), None); | ||||||
|                     } |                     } | ||||||
|  | @ -1817,7 +1819,7 @@ impl<'db> InferenceContext<'db> { | ||||||
|         let ty = match ty.kind(Interner) { |         let ty = match ty.kind(Interner) { | ||||||
|             TyKind::Alias(AliasTy::Projection(proj_ty)) => { |             TyKind::Alias(AliasTy::Projection(proj_ty)) => { | ||||||
|                 let ty = self.table.normalize_projection_ty(proj_ty.clone()); |                 let ty = self.table.normalize_projection_ty(proj_ty.clone()); | ||||||
|                 self.table.resolve_ty_shallow(&ty) |                 self.table.structurally_resolve_type(&ty) | ||||||
|             } |             } | ||||||
|             _ => ty, |             _ => ty, | ||||||
|         }; |         }; | ||||||
|  | @ -2047,7 +2049,7 @@ impl Expectation { | ||||||
|     fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'_>) -> Expectation { |     fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'_>) -> Expectation { | ||||||
|         match self { |         match self { | ||||||
|             Expectation::HasType(ety) => { |             Expectation::HasType(ety) => { | ||||||
|                 let ety = table.resolve_ty_shallow(ety); |                 let ety = table.structurally_resolve_type(ety); | ||||||
|                 if ety.is_ty_var() { Expectation::None } else { Expectation::HasType(ety) } |                 if ety.is_ty_var() { Expectation::None } else { Expectation::HasType(ety) } | ||||||
|             } |             } | ||||||
|             Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()), |             Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()), | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ use crate::{ | ||||||
|     infer::{BreakableKind, CoerceMany, Diverges, coerce::CoerceNever}, |     infer::{BreakableKind, CoerceMany, Diverges, coerce::CoerceNever}, | ||||||
|     make_binders, |     make_binders, | ||||||
|     mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem}, |     mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem}, | ||||||
|  |     next_solver::mapping::ChalkToNextSolver, | ||||||
|     to_assoc_type_id, |     to_assoc_type_id, | ||||||
|     traits::FnTrait, |     traits::FnTrait, | ||||||
|     utils::{self, elaborate_clause_supertraits}, |     utils::{self, elaborate_clause_supertraits}, | ||||||
|  | @ -437,10 +438,10 @@ impl InferenceContext<'_> { | ||||||
|             associated_ty_id: to_assoc_type_id(future_output), |             associated_ty_id: to_assoc_type_id(future_output), | ||||||
|             substitution: Substitution::from1(Interner, ret_param_future.clone()), |             substitution: Substitution::from1(Interner, ret_param_future.clone()), | ||||||
|         }); |         }); | ||||||
|         self.table.register_obligation( |         let goal: crate::Goal = | ||||||
|             crate::AliasEq { alias: future_projection, ty: ret_param_future_output.clone() } |             crate::AliasEq { alias: future_projection, ty: ret_param_future_output.clone() } | ||||||
|                 .cast(Interner), |                 .cast(Interner); | ||||||
|         ); |         self.table.register_obligation(goal.to_nextsolver(self.table.interner)); | ||||||
| 
 | 
 | ||||||
|         Some(FnSubst(Substitution::from_iter( |         Some(FnSubst(Substitution::from_iter( | ||||||
|             Interner, |             Interner, | ||||||
|  | @ -568,7 +569,10 @@ impl InferenceContext<'_> { | ||||||
|         let supplied_sig = self.supplied_sig_of_closure(body, ret_type, arg_types, closure_kind); |         let supplied_sig = self.supplied_sig_of_closure(body, ret_type, arg_types, closure_kind); | ||||||
| 
 | 
 | ||||||
|         let snapshot = self.table.snapshot(); |         let snapshot = self.table.snapshot(); | ||||||
|         if !self.table.unify::<_, crate::next_solver::GenericArgs<'_>>(&expected_sig.substitution.0, &supplied_sig.expected_sig.substitution.0) { |         if !self.table.unify::<_, crate::next_solver::GenericArgs<'_>>( | ||||||
|  |             &expected_sig.substitution.0, | ||||||
|  |             &supplied_sig.expected_sig.substitution.0, | ||||||
|  |         ) { | ||||||
|             self.table.rollback_to(snapshot); |             self.table.rollback_to(snapshot); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,24 +8,27 @@ | ||||||
| use std::iter; | use std::iter; | ||||||
| 
 | 
 | ||||||
| use chalk_ir::{BoundVar, Mutability, TyKind, TyVariableKind, cast::Cast}; | use chalk_ir::{BoundVar, Mutability, TyKind, TyVariableKind, cast::Cast}; | ||||||
| use hir_def::{ | use hir_def::{hir::ExprId, lang_item::LangItem}; | ||||||
|     hir::ExprId, |  | ||||||
|     lang_item::LangItem, |  | ||||||
| }; |  | ||||||
| use rustc_type_ir::solve::Certainty; | use rustc_type_ir::solve::Certainty; | ||||||
| use stdx::always; | use stdx::always; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     autoderef::{Autoderef, AutoderefKind}, db::HirDatabase, infer::{ |     Canonical, FnAbi, FnPointer, FnSig, Goal, Interner, Lifetime, Substitution, TraitEnvironment, | ||||||
|  |     Ty, TyBuilder, TyExt, | ||||||
|  |     autoderef::{Autoderef, AutoderefKind}, | ||||||
|  |     db::HirDatabase, | ||||||
|  |     infer::{ | ||||||
|         Adjust, Adjustment, AutoBorrow, InferOk, InferenceContext, OverloadedDeref, PointerCast, |         Adjust, Adjustment, AutoBorrow, InferOk, InferenceContext, OverloadedDeref, PointerCast, | ||||||
|         TypeError, TypeMismatch, |         TypeError, TypeMismatch, | ||||||
|     }, utils::ClosureSubst, Canonical, FnAbi, FnPointer, FnSig, Goal, InEnvironment, Interner, Lifetime, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt |     }, | ||||||
|  |     next_solver, | ||||||
|  |     utils::ClosureSubst, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use super::unify::InferenceTable; | use super::unify::InferenceTable; | ||||||
| 
 | 
 | ||||||
| pub(crate) type CoerceResult = Result<InferOk<(Vec<Adjustment>, Ty)>, TypeError>; | pub(crate) type CoerceResult<'db> = Result<InferOk<'db, (Vec<Adjustment>, Ty)>, TypeError>; | ||||||
| 
 | 
 | ||||||
| /// Do not require any adjustments, i.e. coerce `x -> x`.
 | /// Do not require any adjustments, i.e. coerce `x -> x`.
 | ||||||
| fn identity(_: Ty) -> Vec<Adjustment> { | fn identity(_: Ty) -> Vec<Adjustment> { | ||||||
|  | @ -37,11 +40,11 @@ fn simple(kind: Adjust) -> impl FnOnce(Ty) -> Vec<Adjustment> { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// This always returns `Ok(...)`.
 | /// This always returns `Ok(...)`.
 | ||||||
| fn success( | fn success<'db>( | ||||||
|     adj: Vec<Adjustment>, |     adj: Vec<Adjustment>, | ||||||
|     target: Ty, |     target: Ty, | ||||||
|     goals: Vec<InEnvironment<Goal>>, |     goals: Vec<next_solver::Goal<'db, next_solver::Predicate<'db>>>, | ||||||
| ) -> CoerceResult { | ) -> CoerceResult<'db> { | ||||||
|     Ok(InferOk { goals, value: (adj, target) }) |     Ok(InferOk { goals, value: (adj, target) }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -107,9 +110,9 @@ impl CoerceMany { | ||||||
|     ///    coerce both to function pointers;
 |     ///    coerce both to function pointers;
 | ||||||
|     ///  - if we were concerned with lifetime subtyping, we'd need to look for a
 |     ///  - if we were concerned with lifetime subtyping, we'd need to look for a
 | ||||||
|     ///    least upper bound.
 |     ///    least upper bound.
 | ||||||
|     pub(super) fn coerce( |     pub(super) fn coerce<'db>( | ||||||
|         &mut self, |         &mut self, | ||||||
|         ctx: &mut InferenceContext<'_>, |         ctx: &mut InferenceContext<'db>, | ||||||
|         expr: Option<ExprId>, |         expr: Option<ExprId>, | ||||||
|         expr_ty: &Ty, |         expr_ty: &Ty, | ||||||
|         cause: CoercionCause, |         cause: CoercionCause, | ||||||
|  | @ -276,7 +279,7 @@ impl InferenceContext<'_> { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl InferenceTable<'_> { | impl<'db> InferenceTable<'db> { | ||||||
|     /// Unify two types, but may coerce the first one to the second one
 |     /// Unify two types, but may coerce the first one to the second one
 | ||||||
|     /// using "implicit coercion rules" if needed.
 |     /// using "implicit coercion rules" if needed.
 | ||||||
|     pub(crate) fn coerce( |     pub(crate) fn coerce( | ||||||
|  | @ -285,8 +288,8 @@ impl InferenceTable<'_> { | ||||||
|         to_ty: &Ty, |         to_ty: &Ty, | ||||||
|         coerce_never: CoerceNever, |         coerce_never: CoerceNever, | ||||||
|     ) -> Result<(Vec<Adjustment>, Ty), TypeError> { |     ) -> Result<(Vec<Adjustment>, Ty), TypeError> { | ||||||
|         let from_ty = self.resolve_ty_shallow(from_ty); |         let from_ty = self.structurally_resolve_type(from_ty); | ||||||
|         let to_ty = self.resolve_ty_shallow(to_ty); |         let to_ty = self.structurally_resolve_type(to_ty); | ||||||
|         match self.coerce_inner(from_ty, &to_ty, coerce_never) { |         match self.coerce_inner(from_ty, &to_ty, coerce_never) { | ||||||
|             Ok(InferOk { value: (adjustments, ty), goals }) => { |             Ok(InferOk { value: (adjustments, ty), goals }) => { | ||||||
|                 self.register_infer_ok(InferOk { value: (), goals }); |                 self.register_infer_ok(InferOk { value: (), goals }); | ||||||
|  | @ -299,10 +302,15 @@ impl InferenceTable<'_> { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn coerce_inner(&mut self, from_ty: Ty, to_ty: &Ty, coerce_never: CoerceNever) -> CoerceResult { |     fn coerce_inner( | ||||||
|  |         &mut self, | ||||||
|  |         from_ty: Ty, | ||||||
|  |         to_ty: &Ty, | ||||||
|  |         coerce_never: CoerceNever, | ||||||
|  |     ) -> CoerceResult<'db> { | ||||||
|         if from_ty.is_never() { |         if from_ty.is_never() { | ||||||
|             if let TyKind::InferenceVar(tv, TyVariableKind::General) = to_ty.kind(Interner) { |             if let TyKind::InferenceVar(tv, TyVariableKind::General) = to_ty.kind(Interner) { | ||||||
|                 self.set_diverging(*tv, TyVariableKind::General, true); |                 self.set_diverging(*tv, TyVariableKind::General); | ||||||
|             } |             } | ||||||
|             if coerce_never == CoerceNever::Yes { |             if coerce_never == CoerceNever::Yes { | ||||||
|                 // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
 |                 // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
 | ||||||
|  | @ -370,7 +378,7 @@ impl InferenceTable<'_> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Unify two types (using sub or lub) and produce a specific coercion.
 |     /// Unify two types (using sub or lub) and produce a specific coercion.
 | ||||||
|     fn unify_and<F>(&mut self, t1: &Ty, t2: &Ty, f: F) -> CoerceResult |     fn unify_and<F>(&mut self, t1: &Ty, t2: &Ty, f: F) -> CoerceResult<'db> | ||||||
|     where |     where | ||||||
|         F: FnOnce(Ty) -> Vec<Adjustment>, |         F: FnOnce(Ty) -> Vec<Adjustment>, | ||||||
|     { |     { | ||||||
|  | @ -378,7 +386,7 @@ impl InferenceTable<'_> { | ||||||
|             .and_then(|InferOk { goals, .. }| success(f(t1.clone()), t1.clone(), goals)) |             .and_then(|InferOk { goals, .. }| success(f(t1.clone()), t1.clone(), goals)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn coerce_ptr(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> CoerceResult { |     fn coerce_ptr(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> CoerceResult<'db> { | ||||||
|         let (is_ref, from_mt, from_inner) = match from_ty.kind(Interner) { |         let (is_ref, from_mt, from_inner) = match from_ty.kind(Interner) { | ||||||
|             TyKind::Ref(mt, _, ty) => (true, mt, ty), |             TyKind::Ref(mt, _, ty) => (true, mt, ty), | ||||||
|             TyKind::Raw(mt, ty) => (false, mt, ty), |             TyKind::Raw(mt, ty) => (false, mt, ty), | ||||||
|  | @ -420,7 +428,7 @@ impl InferenceTable<'_> { | ||||||
|         to_ty: &Ty, |         to_ty: &Ty, | ||||||
|         to_mt: Mutability, |         to_mt: Mutability, | ||||||
|         to_lt: &Lifetime, |         to_lt: &Lifetime, | ||||||
|     ) -> CoerceResult { |     ) -> CoerceResult<'db> { | ||||||
|         let (_from_lt, from_mt) = match from_ty.kind(Interner) { |         let (_from_lt, from_mt) = match from_ty.kind(Interner) { | ||||||
|             TyKind::Ref(mt, lt, _) => { |             TyKind::Ref(mt, lt, _) => { | ||||||
|                 coerce_mutabilities(*mt, to_mt)?; |                 coerce_mutabilities(*mt, to_mt)?; | ||||||
|  | @ -524,7 +532,7 @@ impl InferenceTable<'_> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Attempts to coerce from the type of a Rust function item into a function pointer.
 |     /// Attempts to coerce from the type of a Rust function item into a function pointer.
 | ||||||
|     fn coerce_from_fn_item(&mut self, from_ty: Ty, to_ty: &Ty) -> CoerceResult { |     fn coerce_from_fn_item(&mut self, from_ty: Ty, to_ty: &Ty) -> CoerceResult<'db> { | ||||||
|         match to_ty.kind(Interner) { |         match to_ty.kind(Interner) { | ||||||
|             TyKind::Function(_) => { |             TyKind::Function(_) => { | ||||||
|                 let from_sig = from_ty.callable_sig(self.db).expect("FnDef had no sig"); |                 let from_sig = from_ty.callable_sig(self.db).expect("FnDef had no sig"); | ||||||
|  | @ -566,7 +574,7 @@ impl InferenceTable<'_> { | ||||||
|         from_ty: Ty, |         from_ty: Ty, | ||||||
|         from_f: &FnPointer, |         from_f: &FnPointer, | ||||||
|         to_ty: &Ty, |         to_ty: &Ty, | ||||||
|     ) -> CoerceResult { |     ) -> CoerceResult<'db> { | ||||||
|         self.coerce_from_safe_fn( |         self.coerce_from_safe_fn( | ||||||
|             from_ty, |             from_ty, | ||||||
|             from_f, |             from_f, | ||||||
|  | @ -583,7 +591,7 @@ impl InferenceTable<'_> { | ||||||
|         to_ty: &Ty, |         to_ty: &Ty, | ||||||
|         to_unsafe: F, |         to_unsafe: F, | ||||||
|         normal: G, |         normal: G, | ||||||
|     ) -> CoerceResult |     ) -> CoerceResult<'db> | ||||||
|     where |     where | ||||||
|         F: FnOnce(Ty) -> Vec<Adjustment>, |         F: FnOnce(Ty) -> Vec<Adjustment>, | ||||||
|         G: FnOnce(Ty) -> Vec<Adjustment>, |         G: FnOnce(Ty) -> Vec<Adjustment>, | ||||||
|  | @ -606,7 +614,7 @@ impl InferenceTable<'_> { | ||||||
|         from_ty: Ty, |         from_ty: Ty, | ||||||
|         from_substs: &Substitution, |         from_substs: &Substitution, | ||||||
|         to_ty: &Ty, |         to_ty: &Ty, | ||||||
|     ) -> CoerceResult { |     ) -> CoerceResult<'db> { | ||||||
|         match to_ty.kind(Interner) { |         match to_ty.kind(Interner) { | ||||||
|             // if from_substs is non-capturing (FIXME)
 |             // if from_substs is non-capturing (FIXME)
 | ||||||
|             TyKind::Function(fn_ty) => { |             TyKind::Function(fn_ty) => { | ||||||
|  | @ -631,7 +639,7 @@ impl InferenceTable<'_> { | ||||||
|     /// Coerce a type using `from_ty: CoerceUnsized<ty_ty>`
 |     /// Coerce a type using `from_ty: CoerceUnsized<ty_ty>`
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// See: <https://doc.rust-lang.org/nightly/std/marker/trait.CoerceUnsized.html>
 |     /// See: <https://doc.rust-lang.org/nightly/std/marker/trait.CoerceUnsized.html>
 | ||||||
|     fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> CoerceResult { |     fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> CoerceResult<'db> { | ||||||
|         // These 'if' statements require some explanation.
 |         // These 'if' statements require some explanation.
 | ||||||
|         // The `CoerceUnsized` trait is special - it is only
 |         // The `CoerceUnsized` trait is special - it is only
 | ||||||
|         // possible to write `impl CoerceUnsized<B> for A` where
 |         // possible to write `impl CoerceUnsized<B> for A` where
 | ||||||
|  | @ -707,12 +715,9 @@ impl InferenceTable<'_> { | ||||||
| 
 | 
 | ||||||
|         let goal: Goal = coerce_unsized_tref.cast(Interner); |         let goal: Goal = coerce_unsized_tref.cast(Interner); | ||||||
| 
 | 
 | ||||||
|         self.commit_if_ok(|table| { |         self.commit_if_ok(|table| match table.solve_obligation(goal) { | ||||||
|             match table.solve_obligation(goal) { |  | ||||||
|             Ok(Certainty::Yes) => Ok(()), |             Ok(Certainty::Yes) => Ok(()), | ||||||
|                 Ok(Certainty::Maybe(_)) => Ok(()), |             _ => Err(TypeError), | ||||||
|                 Err(_) => Err(TypeError), |  | ||||||
|             } |  | ||||||
|         })?; |         })?; | ||||||
| 
 | 
 | ||||||
|         let unsize = |         let unsize = | ||||||
|  |  | ||||||
|  | @ -23,9 +23,29 @@ use stdx::always; | ||||||
| use syntax::ast::RangeOp; | use syntax::ast::RangeOp; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     autoderef::{builtin_deref, deref_by_trait, Autoderef}, consteval, generics::generics, infer::{ |     Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext, | ||||||
|         coerce::{CoerceMany, CoerceNever, CoercionCause}, find_continuable, pat::contains_explicit_ref_binding, BreakableKind |     DeclOrigin, IncorrectGenericsLenKind, Interner, LifetimeElisionKind, Rawness, Scalar, | ||||||
|     }, lang_items::lang_items_for_bin_op, lower::{lower_to_chalk_mutability, path::{substs_from_args_and_bindings, GenericArgsLowerer, TypeLikeConst}, ParamLoweringMode}, mapping::{from_chalk, ToChalk}, method_resolution::{self, VisibleFromModule}, next_solver::mapping::ChalkToNextSolver, primitive::{self, UintTy}, static_lifetime, to_chalk_trait_id, traits::FnTrait, Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext, DeclOrigin, IncorrectGenericsLenKind, Interner, LifetimeElisionKind, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind |     Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, | ||||||
|  |     autoderef::{Autoderef, builtin_deref, deref_by_trait}, | ||||||
|  |     consteval, | ||||||
|  |     generics::generics, | ||||||
|  |     infer::{ | ||||||
|  |         BreakableKind, | ||||||
|  |         coerce::{CoerceMany, CoerceNever, CoercionCause}, | ||||||
|  |         find_continuable, | ||||||
|  |         pat::contains_explicit_ref_binding, | ||||||
|  |     }, | ||||||
|  |     lang_items::lang_items_for_bin_op, | ||||||
|  |     lower::{ | ||||||
|  |         ParamLoweringMode, lower_to_chalk_mutability, | ||||||
|  |         path::{GenericArgsLowerer, TypeLikeConst, substs_from_args_and_bindings}, | ||||||
|  |     }, | ||||||
|  |     mapping::{ToChalk, from_chalk}, | ||||||
|  |     method_resolution::{self, VisibleFromModule}, | ||||||
|  |     next_solver::mapping::ChalkToNextSolver, | ||||||
|  |     primitive::{self, UintTy}, | ||||||
|  |     static_lifetime, to_chalk_trait_id, | ||||||
|  |     traits::FnTrait, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use super::{ | use super::{ | ||||||
|  | @ -383,7 +403,7 @@ impl InferenceContext<'_> { | ||||||
|                     let matchee_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); |                     let matchee_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); | ||||||
|                     let mut all_arms_diverge = Diverges::Always; |                     let mut all_arms_diverge = Diverges::Always; | ||||||
|                     for arm in arms.iter() { |                     for arm in arms.iter() { | ||||||
|                         let input_ty = self.resolve_ty_shallow(&input_ty); |                         let input_ty = self.table.structurally_resolve_type(&input_ty); | ||||||
|                         self.infer_top_pat(arm.pat, &input_ty, None); |                         self.infer_top_pat(arm.pat, &input_ty, None); | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|  | @ -633,7 +653,7 @@ impl InferenceContext<'_> { | ||||||
|             &Expr::Box { expr } => self.infer_expr_box(expr, expected), |             &Expr::Box { expr } => self.infer_expr_box(expr, expected), | ||||||
|             Expr::UnaryOp { expr, op } => { |             Expr::UnaryOp { expr, op } => { | ||||||
|                 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none(), ExprIsRead::Yes); |                 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none(), ExprIsRead::Yes); | ||||||
|                 let inner_ty = self.resolve_ty_shallow(&inner_ty); |                 let inner_ty = self.table.structurally_resolve_type(&inner_ty); | ||||||
|                 // FIXME: Note down method resolution her
 |                 // FIXME: Note down method resolution her
 | ||||||
|                 match op { |                 match op { | ||||||
|                     UnaryOp::Deref => { |                     UnaryOp::Deref => { | ||||||
|  | @ -651,7 +671,7 @@ impl InferenceContext<'_> { | ||||||
|                             ); |                             ); | ||||||
|                         } |                         } | ||||||
|                         if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) { |                         if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) { | ||||||
|                             self.resolve_ty_shallow(derefed) |                             self.table.structurally_resolve_type(derefed) | ||||||
|                         } else { |                         } else { | ||||||
|                             deref_by_trait(&mut self.table, inner_ty, false) |                             deref_by_trait(&mut self.table, inner_ty, false) | ||||||
|                                 .unwrap_or_else(|| self.err_ty()) |                                 .unwrap_or_else(|| self.err_ty()) | ||||||
|  | @ -807,10 +827,10 @@ impl InferenceContext<'_> { | ||||||
|                 let index_ty = self.infer_expr(*index, &Expectation::none(), ExprIsRead::Yes); |                 let index_ty = self.infer_expr(*index, &Expectation::none(), ExprIsRead::Yes); | ||||||
| 
 | 
 | ||||||
|                 if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) { |                 if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) { | ||||||
|                     let canonicalized = ChalkToNextSolver::from_nextsolver(self.canonicalize(base_ty.clone().to_nextsolver(self.table.interner)), self.table.interner); |                     let canonicalized = | ||||||
|  |                         self.canonicalize(base_ty.clone().to_nextsolver(self.table.interner)); | ||||||
|                     let receiver_adjustments = method_resolution::resolve_indexing_op( |                     let receiver_adjustments = method_resolution::resolve_indexing_op( | ||||||
|                         self.db, |                         &mut self.table, | ||||||
|                         self.table.trait_env.clone(), |  | ||||||
|                         canonicalized, |                         canonicalized, | ||||||
|                         index_trait, |                         index_trait, | ||||||
|                     ); |                     ); | ||||||
|  | @ -983,7 +1003,7 @@ impl InferenceContext<'_> { | ||||||
|                     // allows them to be inferred based on how they are used later in the
 |                     // allows them to be inferred based on how they are used later in the
 | ||||||
|                     // function.
 |                     // function.
 | ||||||
|                     if is_input { |                     if is_input { | ||||||
|                         let ty = this.resolve_ty_shallow(&ty); |                         let ty = this.table.structurally_resolve_type(&ty); | ||||||
|                         match ty.kind(Interner) { |                         match ty.kind(Interner) { | ||||||
|                             TyKind::FnDef(def, parameters) => { |                             TyKind::FnDef(def, parameters) => { | ||||||
|                                 let fnptr_ty = TyKind::Function( |                                 let fnptr_ty = TyKind::Function( | ||||||
|  | @ -1405,10 +1425,11 @@ impl InferenceContext<'_> { | ||||||
|             // use knowledge of built-in binary ops, which can sometimes help inference
 |             // use knowledge of built-in binary ops, which can sometimes help inference
 | ||||||
|             let builtin_ret = self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op); |             let builtin_ret = self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op); | ||||||
|             self.unify(&builtin_ret, &ret_ty); |             self.unify(&builtin_ret, &ret_ty); | ||||||
|         } |             builtin_ret | ||||||
| 
 |         } else { | ||||||
|             ret_ty |             ret_ty | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     fn infer_block( |     fn infer_block( | ||||||
|         &mut self, |         &mut self, | ||||||
|  | @ -1660,7 +1681,8 @@ impl InferenceContext<'_> { | ||||||
|             None => { |             None => { | ||||||
|                 // no field found, lets attempt to resolve it like a function so that IDE things
 |                 // no field found, lets attempt to resolve it like a function so that IDE things
 | ||||||
|                 // work out while people are typing
 |                 // work out while people are typing
 | ||||||
|                 let canonicalized_receiver = self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner)); |                 let canonicalized_receiver = | ||||||
|  |                     self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner)); | ||||||
|                 let resolved = method_resolution::lookup_method( |                 let resolved = method_resolution::lookup_method( | ||||||
|                     self.db, |                     self.db, | ||||||
|                     &canonicalized_receiver, |                     &canonicalized_receiver, | ||||||
|  | @ -1806,7 +1828,8 @@ impl InferenceContext<'_> { | ||||||
|         expected: &Expectation, |         expected: &Expectation, | ||||||
|     ) -> Ty { |     ) -> Ty { | ||||||
|         let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::Yes); |         let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::Yes); | ||||||
|         let canonicalized_receiver = self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner)); |         let canonicalized_receiver = | ||||||
|  |             self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner)); | ||||||
| 
 | 
 | ||||||
|         let resolved = method_resolution::lookup_method( |         let resolved = method_resolution::lookup_method( | ||||||
|             self.db, |             self.db, | ||||||
|  | @ -2216,7 +2239,7 @@ impl InferenceContext<'_> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn register_obligations_for_call(&mut self, callable_ty: &Ty) { |     fn register_obligations_for_call(&mut self, callable_ty: &Ty) { | ||||||
|         let callable_ty = self.resolve_ty_shallow(callable_ty); |         let callable_ty = self.table.structurally_resolve_type(callable_ty); | ||||||
|         if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) { |         if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) { | ||||||
|             let def: CallableDefId = from_chalk(self.db, *fn_def); |             let def: CallableDefId = from_chalk(self.db, *fn_def); | ||||||
|             let generic_predicates = |             let generic_predicates = | ||||||
|  | @ -2305,9 +2328,9 @@ impl InferenceContext<'_> { | ||||||
| 
 | 
 | ||||||
|     /// Dereferences a single level of immutable referencing.
 |     /// Dereferences a single level of immutable referencing.
 | ||||||
|     fn deref_ty_if_possible(&mut self, ty: &Ty) -> Ty { |     fn deref_ty_if_possible(&mut self, ty: &Ty) -> Ty { | ||||||
|         let ty = self.resolve_ty_shallow(ty); |         let ty = self.table.structurally_resolve_type(ty); | ||||||
|         match ty.kind(Interner) { |         match ty.kind(Interner) { | ||||||
|             TyKind::Ref(Mutability::Not, _, inner) => self.resolve_ty_shallow(inner), |             TyKind::Ref(Mutability::Not, _, inner) => self.table.structurally_resolve_type(inner), | ||||||
|             _ => ty, |             _ => ty, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -190,7 +190,7 @@ impl InferenceContext<'_> { | ||||||
|         subs: &[PatId], |         subs: &[PatId], | ||||||
|         decl: Option<DeclContext>, |         decl: Option<DeclContext>, | ||||||
|     ) -> Ty { |     ) -> Ty { | ||||||
|         let expected = self.resolve_ty_shallow(expected); |         let expected = self.table.structurally_resolve_type(expected); | ||||||
|         let expectations = match expected.as_tuple() { |         let expectations = match expected.as_tuple() { | ||||||
|             Some(parameters) => parameters.as_slice(Interner), |             Some(parameters) => parameters.as_slice(Interner), | ||||||
|             _ => &[], |             _ => &[], | ||||||
|  | @ -238,7 +238,7 @@ impl InferenceContext<'_> { | ||||||
|         mut default_bm: BindingMode, |         mut default_bm: BindingMode, | ||||||
|         decl: Option<DeclContext>, |         decl: Option<DeclContext>, | ||||||
|     ) -> Ty { |     ) -> Ty { | ||||||
|         let mut expected = self.resolve_ty_shallow(expected); |         let mut expected = self.table.structurally_resolve_type(expected); | ||||||
| 
 | 
 | ||||||
|         if matches!(&self.body[pat], Pat::Ref { .. }) || self.inside_assignment { |         if matches!(&self.body[pat], Pat::Ref { .. }) || self.inside_assignment { | ||||||
|             cov_mark::hit!(match_ergonomics_ref); |             cov_mark::hit!(match_ergonomics_ref); | ||||||
|  | @ -251,7 +251,7 @@ impl InferenceContext<'_> { | ||||||
|             let mut pat_adjustments = Vec::new(); |             let mut pat_adjustments = Vec::new(); | ||||||
|             while let Some((inner, _lifetime, mutability)) = expected.as_reference() { |             while let Some((inner, _lifetime, mutability)) = expected.as_reference() { | ||||||
|                 pat_adjustments.push(expected.clone()); |                 pat_adjustments.push(expected.clone()); | ||||||
|                 expected = self.resolve_ty_shallow(inner); |                 expected = self.table.structurally_resolve_type(inner); | ||||||
|                 default_bm = match default_bm { |                 default_bm = match default_bm { | ||||||
|                     BindingMode::Move => BindingMode::Ref(mutability), |                     BindingMode::Move => BindingMode::Ref(mutability), | ||||||
|                     BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not), |                     BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not), | ||||||
|  | @ -494,7 +494,7 @@ impl InferenceContext<'_> { | ||||||
|         default_bm: BindingMode, |         default_bm: BindingMode, | ||||||
|         decl: Option<DeclContext>, |         decl: Option<DeclContext>, | ||||||
|     ) -> Ty { |     ) -> Ty { | ||||||
|         let expected = self.resolve_ty_shallow(expected); |         let expected = self.table.structurally_resolve_type(expected); | ||||||
| 
 | 
 | ||||||
|         // If `expected` is an infer ty, we try to equate it to an array if the given pattern
 |         // If `expected` is an infer ty, we try to equate it to an array if the given pattern
 | ||||||
|         // allows it. See issue #16609
 |         // allows it. See issue #16609
 | ||||||
|  | @ -506,7 +506,7 @@ impl InferenceContext<'_> { | ||||||
|             self.unify(&expected, &resolved_array_ty); |             self.unify(&expected, &resolved_array_ty); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let expected = self.resolve_ty_shallow(&expected); |         let expected = self.table.structurally_resolve_type(&expected); | ||||||
|         let elem_ty = match expected.kind(Interner) { |         let elem_ty = match expected.kind(Interner) { | ||||||
|             TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(), |             TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(), | ||||||
|             _ => self.err_ty(), |             _ => self.err_ty(), | ||||||
|  | @ -542,7 +542,7 @@ impl InferenceContext<'_> { | ||||||
|         if let Expr::Literal(Literal::ByteString(_)) = self.body[expr] |         if let Expr::Literal(Literal::ByteString(_)) = self.body[expr] | ||||||
|             && let Some((inner, ..)) = expected.as_reference() |             && let Some((inner, ..)) = expected.as_reference() | ||||||
|         { |         { | ||||||
|             let inner = self.resolve_ty_shallow(inner); |             let inner = self.table.structurally_resolve_type(inner); | ||||||
|             if matches!(inner.kind(Interner), TyKind::Slice(_)) { |             if matches!(inner.kind(Interner), TyKind::Slice(_)) { | ||||||
|                 let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner); |                 let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner); | ||||||
|                 let slice_ty = TyKind::Slice(elem_ty).intern(Interner); |                 let slice_ty = TyKind::Slice(elem_ty).intern(Interner); | ||||||
|  |  | ||||||
|  | @ -10,7 +10,15 @@ use hir_expand::name::Name; | ||||||
| use stdx::never; | use stdx::never; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     builder::ParamKind, consteval, error_lifetime, generics::generics, infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext, method_resolution::{self, VisibleFromModule}, next_solver::mapping::ChalkToNextSolver, to_chalk_trait_id, InferenceDiagnostic, Interner, LifetimeElisionKind, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, ValueTyDefId |     InferenceDiagnostic, Interner, LifetimeElisionKind, Substitution, TraitRef, TraitRefExt, Ty, | ||||||
|  |     TyBuilder, TyExt, TyKind, ValueTyDefId, | ||||||
|  |     builder::ParamKind, | ||||||
|  |     consteval, error_lifetime, | ||||||
|  |     generics::generics, | ||||||
|  |     infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext, | ||||||
|  |     method_resolution::{self, VisibleFromModule}, | ||||||
|  |     next_solver::mapping::ChalkToNextSolver, | ||||||
|  |     to_chalk_trait_id, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource}; | use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource}; | ||||||
|  | @ -384,7 +392,7 @@ impl InferenceContext<'_> { | ||||||
|         name: &Name, |         name: &Name, | ||||||
|         id: ExprOrPatId, |         id: ExprOrPatId, | ||||||
|     ) -> Option<(ValueNs, Substitution)> { |     ) -> Option<(ValueNs, Substitution)> { | ||||||
|         let ty = self.resolve_ty_shallow(ty); |         let ty = self.table.structurally_resolve_type(ty); | ||||||
|         let (enum_id, subst) = match ty.as_adt() { |         let (enum_id, subst) = match ty.as_adt() { | ||||||
|             Some((AdtId::EnumId(e), subst)) => (e, subst), |             Some((AdtId::EnumId(e), subst)) => (e, subst), | ||||||
|             _ => return None, |             _ => return None, | ||||||
|  |  | ||||||
|  | @ -3,7 +3,8 @@ | ||||||
| use std::{fmt, mem}; | use std::{fmt, mem}; | ||||||
| 
 | 
 | ||||||
| use chalk_ir::{ | use chalk_ir::{ | ||||||
|     cast::Cast, fold::TypeFoldable, interner::HasInterner, CanonicalVarKind, FloatTy, IntTy, TyVariableKind, |     CanonicalVarKind, FloatTy, IntTy, TyVariableKind, cast::Cast, fold::TypeFoldable, | ||||||
|  |     interner::HasInterner, | ||||||
| }; | }; | ||||||
| use either::Either; | use either::Either; | ||||||
| use hir_def::{AdtId, lang_item::LangItem}; | use hir_def::{AdtId, lang_item::LangItem}; | ||||||
|  | @ -11,13 +12,36 @@ use hir_expand::name::Name; | ||||||
| use intern::sym; | use intern::sym; | ||||||
| use rustc_hash::{FxHashMap, FxHashSet}; | use rustc_hash::{FxHashMap, FxHashSet}; | ||||||
| use rustc_next_trait_solver::solve::HasChanged; | use rustc_next_trait_solver::solve::HasChanged; | ||||||
| use rustc_type_ir::{inherent::Span, relate::{solver_relating::RelateExt, Relate}, solve::{Certainty, NoSolution}, FloatVid, IntVid, TyVid}; | use rustc_type_ir::{ | ||||||
|  |     AliasRelationDirection, FloatVid, IntVid, TyVid, | ||||||
|  |     inherent::{Span, Term as _}, | ||||||
|  |     relate::{Relate, solver_relating::RelateExt}, | ||||||
|  |     solve::{Certainty, NoSolution}, | ||||||
|  | }; | ||||||
| use smallvec::SmallVec; | use smallvec::SmallVec; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use super::{InferOk, InferResult, InferenceContext, TypeError}; | use super::{InferOk, InferResult, InferenceContext, TypeError}; | ||||||
| use crate::{ | use crate::{ | ||||||
|     consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts, next_solver::{infer::{canonical::canonicalizer::OriginalQueryValues, snapshot::CombinedSnapshot, DbInternerInferExt, InferCtxt}, mapping::{ChalkToNextSolver, InferenceVarExt}, DbInterner, ParamEnvAnd, SolverDefIds}, to_chalk_trait_id, traits::{next_trait_solve, next_trait_solve_canonical, next_trait_solve_in_ctxt, FnTrait, NextTraitSolveResult}, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause |     AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, DomainGoal, | ||||||
|  |     GenericArg, GenericArgData, Goal, GoalData, InEnvironment, InferenceVar, Interner, Lifetime, | ||||||
|  |     OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Substitution, TraitEnvironment, | ||||||
|  |     TraitRef, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause, | ||||||
|  |     consteval::unknown_const, | ||||||
|  |     db::HirDatabase, | ||||||
|  |     fold_generic_args, fold_tys_and_consts, | ||||||
|  |     next_solver::{ | ||||||
|  |         self, Binder, DbInterner, ParamEnvAnd, Predicate, PredicateKind, SolverDefIds, Term, | ||||||
|  |         infer::{ | ||||||
|  |             DbInternerInferExt, InferCtxt, canonical::canonicalizer::OriginalQueryValues, | ||||||
|  |             snapshot::CombinedSnapshot, | ||||||
|  |         }, | ||||||
|  |         mapping::{ChalkToNextSolver, InferenceVarExt, NextSolverToChalk}, | ||||||
|  |     }, | ||||||
|  |     to_chalk_trait_id, | ||||||
|  |     traits::{ | ||||||
|  |         FnTrait, NextTraitSolveResult, next_trait_solve_canonical_in_ctxt, next_trait_solve_in_ctxt, | ||||||
|  |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| impl<'db> InferenceContext<'db> { | impl<'db> InferenceContext<'db> { | ||||||
|  | @ -38,7 +62,7 @@ impl<'db> InferenceContext<'db> { | ||||||
|         let pending_obligations = mem::take(&mut self.table.pending_obligations); |         let pending_obligations = mem::take(&mut self.table.pending_obligations); | ||||||
|         let obligations = pending_obligations |         let obligations = pending_obligations | ||||||
|             .iter() |             .iter() | ||||||
|             .filter_map(|obligation| match obligation.goal.data(Interner) { |             .filter_map(|obligation| match obligation.to_chalk(self.table.interner).goal.data(Interner) { | ||||||
|                 GoalData::DomainGoal(DomainGoal::Holds(clause)) => { |                 GoalData::DomainGoal(DomainGoal::Holds(clause)) => { | ||||||
|                     let ty = match clause { |                     let ty = match clause { | ||||||
|                         WhereClause::AliasEq(AliasEq { |                         WhereClause::AliasEq(AliasEq { | ||||||
|  | @ -67,51 +91,6 @@ impl<'db> InferenceContext<'db> { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone)] |  | ||||||
| pub(crate) struct Canonicalized<T> |  | ||||||
| where |  | ||||||
|     T: HasInterner<Interner = Interner>, |  | ||||||
| { |  | ||||||
|     pub(crate) value: Canonical<T>, |  | ||||||
|     free_vars: Vec<GenericArg>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl<T: HasInterner<Interner = Interner>> Canonicalized<T> { |  | ||||||
|     pub(crate) fn apply_solution( |  | ||||||
|         &self, |  | ||||||
|         ctx: &mut InferenceTable<'_>, |  | ||||||
|         solution: Canonical<Substitution>, |  | ||||||
|     ) { |  | ||||||
|         // the solution may contain new variables, which we need to convert to new inference vars
 |  | ||||||
|         let new_vars = Substitution::from_iter( |  | ||||||
|             Interner, |  | ||||||
|             solution.binders.iter(Interner).map(|k| match &k.kind { |  | ||||||
|                 VariableKind::Ty(TyVariableKind::General) => ctx.new_type_var().cast(Interner), |  | ||||||
|                 VariableKind::Ty(TyVariableKind::Integer) => ctx.new_integer_var().cast(Interner), |  | ||||||
|                 VariableKind::Ty(TyVariableKind::Float) => ctx.new_float_var().cast(Interner), |  | ||||||
|                 // Chalk can sometimes return new lifetime variables. We just replace them by errors
 |  | ||||||
|                 // for now.
 |  | ||||||
|                 VariableKind::Lifetime => ctx.new_lifetime_var().cast(Interner), |  | ||||||
|                 VariableKind::Const(ty) => ctx.new_const_var(ty.clone()).cast(Interner), |  | ||||||
|             }), |  | ||||||
|         ); |  | ||||||
|         for (i, v) in solution.value.iter(Interner).enumerate() { |  | ||||||
|             let var = &self.free_vars[i]; |  | ||||||
|             if let Some(ty) = v.ty(Interner) { |  | ||||||
|                 // eagerly replace projections in the type; we may be getting types
 |  | ||||||
|                 // e.g. from where clauses where this hasn't happened yet
 |  | ||||||
|                 let ty = ctx.normalize_associated_types_in(new_vars.apply(ty.clone(), Interner)); |  | ||||||
|                 tracing::debug!("unifying {:?} {:?}", var, ty); |  | ||||||
|                 ctx.unify(var.assert_ty_ref(Interner), &ty); |  | ||||||
|             } else { |  | ||||||
|                 let v = new_vars.apply(v.clone(), Interner); |  | ||||||
|                 tracing::debug!("try_unifying {:?} {:?}", var, v); |  | ||||||
|                 let _ = ctx.try_unify(var, &v); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// Check if types unify.
 | /// Check if types unify.
 | ||||||
| ///
 | ///
 | ||||||
| /// Note that we consider placeholder types to unify with everything.
 | /// Note that we consider placeholder types to unify with everything.
 | ||||||
|  | @ -207,23 +186,21 @@ bitflags::bitflags! { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>; |  | ||||||
| 
 |  | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub(crate) struct InferenceTable<'a> { | pub(crate) struct InferenceTable<'a> { | ||||||
|     pub(crate) db: &'a dyn HirDatabase, |     pub(crate) db: &'a dyn HirDatabase, | ||||||
|     pub(crate) interner: DbInterner<'a>, |     pub(crate) interner: DbInterner<'a>, | ||||||
|     pub(crate) trait_env: Arc<TraitEnvironment>, |     pub(crate) trait_env: Arc<TraitEnvironment>, | ||||||
|     pub(crate) tait_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>, |     pub(crate) tait_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>, | ||||||
|     infer_ctxt: InferCtxt<'a>, |     pub(crate) infer_ctxt: InferCtxt<'a>, | ||||||
|     diverging_tys: FxHashSet<Ty>, |     diverging_tys: FxHashSet<Ty>, | ||||||
|     pending_obligations: Vec<InEnvironment<Goal>>, |     pending_obligations: Vec<next_solver::Goal<'a, next_solver::Predicate<'a>>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub(crate) struct InferenceTableSnapshot { | pub(crate) struct InferenceTableSnapshot<'a> { | ||||||
|     ctxt_snapshot: CombinedSnapshot, |     ctxt_snapshot: CombinedSnapshot, | ||||||
|     diverging_tys: FxHashSet<Ty>, |     diverging_tys: FxHashSet<Ty>, | ||||||
|     pending_obligations: Vec<InEnvironment<Goal>>, |     pending_obligations: Vec<next_solver::Goal<'a, next_solver::Predicate<'a>>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'a> InferenceTable<'a> { | impl<'a> InferenceTable<'a> { | ||||||
|  | @ -234,7 +211,9 @@ impl<'a> InferenceTable<'a> { | ||||||
|             interner, |             interner, | ||||||
|             trait_env, |             trait_env, | ||||||
|             tait_coercion_table: None, |             tait_coercion_table: None, | ||||||
|             infer_ctxt: interner.infer_ctxt().build(rustc_type_ir::TypingMode::Analysis { defining_opaque_types_and_generators: SolverDefIds::new_from_iter(interner, []) }), |             infer_ctxt: interner.infer_ctxt().build(rustc_type_ir::TypingMode::Analysis { | ||||||
|  |                 defining_opaque_types_and_generators: SolverDefIds::new_from_iter(interner, []), | ||||||
|  |             }), | ||||||
|             diverging_tys: FxHashSet::default(), |             diverging_tys: FxHashSet::default(), | ||||||
|             pending_obligations: Vec::new(), |             pending_obligations: Vec::new(), | ||||||
|         } |         } | ||||||
|  | @ -250,40 +229,55 @@ impl<'a> InferenceTable<'a> { | ||||||
|         let mut new_tys = FxHashSet::default(); |         let mut new_tys = FxHashSet::default(); | ||||||
|         for ty in self.diverging_tys.iter() { |         for ty in self.diverging_tys.iter() { | ||||||
|             match ty.kind(Interner) { |             match ty.kind(Interner) { | ||||||
|                 TyKind::InferenceVar(var, kind) => { |                 TyKind::InferenceVar(var, kind) => match kind { | ||||||
|                     match kind { |  | ||||||
|                     TyVariableKind::General => { |                     TyVariableKind::General => { | ||||||
|                             let root = InferenceVar::from(self.infer_ctxt.root_var(TyVid::from_u32(var.index())).as_u32()); |                         let root = InferenceVar::from( | ||||||
|  |                             self.infer_ctxt.root_var(TyVid::from_u32(var.index())).as_u32(), | ||||||
|  |                         ); | ||||||
|                         if root.index() != var.index() { |                         if root.index() != var.index() { | ||||||
|                             new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner)); |                             new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner)); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     TyVariableKind::Integer => { |                     TyVariableKind::Integer => { | ||||||
|                             let root = InferenceVar::from(self.infer_ctxt.inner.borrow_mut().int_unification_table().find(IntVid::from_usize(var.index() as usize)).as_u32()); |                         let root = InferenceVar::from( | ||||||
|  |                             self.infer_ctxt | ||||||
|  |                                 .inner | ||||||
|  |                                 .borrow_mut() | ||||||
|  |                                 .int_unification_table() | ||||||
|  |                                 .find(IntVid::from_usize(var.index() as usize)) | ||||||
|  |                                 .as_u32(), | ||||||
|  |                         ); | ||||||
|                         if root.index() != var.index() { |                         if root.index() != var.index() { | ||||||
|                             new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner)); |                             new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner)); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     TyVariableKind::Float => { |                     TyVariableKind::Float => { | ||||||
|                             let root = InferenceVar::from(self.infer_ctxt.inner.borrow_mut().float_unification_table().find(FloatVid::from_usize(var.index() as usize)).as_u32()); |                         let root = InferenceVar::from( | ||||||
|  |                             self.infer_ctxt | ||||||
|  |                                 .inner | ||||||
|  |                                 .borrow_mut() | ||||||
|  |                                 .float_unification_table() | ||||||
|  |                                 .find(FloatVid::from_usize(var.index() as usize)) | ||||||
|  |                                 .as_u32(), | ||||||
|  |                         ); | ||||||
|                         if root.index() != var.index() { |                         if root.index() != var.index() { | ||||||
|                             new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner)); |                             new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner)); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     } |                 }, | ||||||
|                 } |  | ||||||
|                 _ => {} |                 _ => {} | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         self.diverging_tys.extend(new_tys.into_iter()); |         self.diverging_tys.extend(new_tys); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(super) fn set_diverging(&mut self, iv: InferenceVar, kind: TyVariableKind, diverging: bool) { |     pub(super) fn set_diverging(&mut self, iv: InferenceVar, kind: TyVariableKind) { | ||||||
|         self.diverging_tys.insert(TyKind::InferenceVar(iv, kind).intern(Interner)); |         self.diverging_tys.insert(TyKind::InferenceVar(iv, kind).intern(Interner)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { |     fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { | ||||||
|         let is_diverging = self.diverging_tys.contains(&TyKind::InferenceVar(iv, kind).intern(Interner)); |         let is_diverging = | ||||||
|  |             self.diverging_tys.contains(&TyKind::InferenceVar(iv, kind).intern(Interner)); | ||||||
|         if is_diverging { |         if is_diverging { | ||||||
|             return TyKind::Never.intern(Interner); |             return TyKind::Never.intern(Interner); | ||||||
|         } |         } | ||||||
|  | @ -295,19 +289,6 @@ impl<'a> InferenceTable<'a> { | ||||||
|         .intern(Interner) |         .intern(Interner) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn canonicalize_with_free_vars<T>(&mut self, t: ParamEnvAnd<'a, T>) -> (rustc_type_ir::Canonical<DbInterner<'a>, ParamEnvAnd<'a, T>>, OriginalQueryValues<'a>) |  | ||||||
|     where |  | ||||||
|         T: rustc_type_ir::TypeFoldable<DbInterner<'a>>, |  | ||||||
|     { |  | ||||||
|         // try to resolve obligations before canonicalizing, since this might
 |  | ||||||
|         // result in new knowledge about variables
 |  | ||||||
|         self.resolve_obligations_as_possible(); |  | ||||||
| 
 |  | ||||||
|         let mut orig_values = OriginalQueryValues::default(); |  | ||||||
|         let result = self.infer_ctxt.canonicalize_query(t, &mut orig_values); |  | ||||||
|         (result.canonical, orig_values) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub(crate) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'a>, T> |     pub(crate) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'a>, T> | ||||||
|     where |     where | ||||||
|         T: rustc_type_ir::TypeFoldable<DbInterner<'a>>, |         T: rustc_type_ir::TypeFoldable<DbInterner<'a>>, | ||||||
|  | @ -341,7 +322,7 @@ impl<'a> InferenceTable<'a> { | ||||||
|                             self.resolve_ty_shallow(&ty) |                             self.resolve_ty_shallow(&ty) | ||||||
|                         } |                         } | ||||||
|                         TyKind::AssociatedType(id, subst) => { |                         TyKind::AssociatedType(id, subst) => { | ||||||
|                             return Either::Left(self.resolve_ty_shallow(&ty)); |                             // return Either::Left(self.resolve_ty_shallow(&ty));
 | ||||||
|                             if ty.data(Interner).flags.intersects( |                             if ty.data(Interner).flags.intersects( | ||||||
|                                 chalk_ir::TypeFlags::HAS_TY_INFER |                                 chalk_ir::TypeFlags::HAS_TY_INFER | ||||||
|                                     | chalk_ir::TypeFlags::HAS_CT_INFER, |                                     | chalk_ir::TypeFlags::HAS_CT_INFER, | ||||||
|  | @ -365,51 +346,44 @@ impl<'a> InferenceTable<'a> { | ||||||
|                             ); |                             ); | ||||||
|                             let in_env = InEnvironment::new(&self.trait_env.env, goal); |                             let in_env = InEnvironment::new(&self.trait_env.env, goal); | ||||||
|                             let goal = in_env.to_nextsolver(self.interner); |                             let goal = in_env.to_nextsolver(self.interner); | ||||||
|                             let goal = ParamEnvAnd { param_env: goal.param_env, value: goal.predicate }; |                             let goal = | ||||||
|  |                                 ParamEnvAnd { param_env: goal.param_env, value: goal.predicate }; | ||||||
| 
 | 
 | ||||||
|                             let (canonical_goal, _orig_values) = { |                             let (canonical_goal, orig_values) = { | ||||||
|                                 let mut orig_values = OriginalQueryValues::default(); |                                 let mut orig_values = OriginalQueryValues::default(); | ||||||
|                                 let result = self.infer_ctxt.canonicalize_query(goal, &mut orig_values); |                                 let result = | ||||||
|  |                                     self.infer_ctxt.canonicalize_query(goal, &mut orig_values); | ||||||
|                                 (result.canonical, orig_values) |                                 (result.canonical, orig_values) | ||||||
|                             }; |                             }; | ||||||
|                             let canonical_goal = rustc_type_ir::Canonical { |                             let canonical_goal = rustc_type_ir::Canonical { | ||||||
|                                 max_universe: canonical_goal.max_universe, |                                 max_universe: canonical_goal.max_universe, | ||||||
|                                 variables: canonical_goal.variables, |                                 variables: canonical_goal.variables, | ||||||
|                                 value: crate::next_solver::Goal { param_env: canonical_goal.value.param_env, predicate: canonical_goal.value.value }, |                                 value: crate::next_solver::Goal { | ||||||
|  |                                     param_env: canonical_goal.value.param_env, | ||||||
|  |                                     predicate: canonical_goal.value.value, | ||||||
|  |                                 }, | ||||||
|                             }; |                             }; | ||||||
|                             let solution = next_trait_solve_canonical( |                             let solution = next_trait_solve_canonical_in_ctxt( | ||||||
|                                 self.db, |                                 &self.infer_ctxt, | ||||||
|                                 self.trait_env.krate, |                                 canonical_goal, | ||||||
|                                 self.trait_env.block, |  | ||||||
|                                 canonical_goal.clone(), |  | ||||||
|                             ); |                             ); | ||||||
|                             if let NextTraitSolveResult::Certain(canonical_subst) = solution { |                             if let NextTraitSolveResult::Certain(canonical_subst) = solution { | ||||||
|                                 // This is not great :) But let's just assert this for now and come back to it later.
 |                                 let subst = self.instantiate_canonical(canonical_subst).subst; | ||||||
|                                 if canonical_subst.value.subst.len(Interner) != 1 { |                                 if subst.len(Interner) != orig_values.var_values.len() { | ||||||
|                                     ty |                                     ty | ||||||
|                                 } else { |                                 } else { | ||||||
|                                     let normalized = canonical_subst.value.subst.as_slice(Interner) |                                     let target_ty = var.to_nextsolver(self.interner); | ||||||
|                                         [0] |                                     subst | ||||||
|                                     .assert_ty_ref(Interner); |                                         .iter(Interner) | ||||||
|                                     match normalized.kind(Interner) { |                                         .zip(orig_values.var_values.iter()) | ||||||
|                                         TyKind::Alias(AliasTy::Projection(proj_ty)) => { |                                         .find_map(|(new, orig)| { | ||||||
|                                             if id == &proj_ty.associated_ty_id |                                             if orig.ty() == Some(target_ty) { | ||||||
|                                                 && subst == &proj_ty.substitution |                                                 Some(new.assert_ty_ref(Interner).clone()) | ||||||
|                                             { |  | ||||||
|                                                 ty |  | ||||||
|                                             } else { |                                             } else { | ||||||
|                                                 normalized.clone() |                                                 None | ||||||
|                                             } |  | ||||||
|                                         } |  | ||||||
|                                         TyKind::AssociatedType(new_id, new_subst) => { |  | ||||||
|                                             if new_id == id && new_subst == subst { |  | ||||||
|                                                 ty |  | ||||||
|                                             } else { |  | ||||||
|                                                 normalized.clone() |  | ||||||
|                                             } |  | ||||||
|                                         } |  | ||||||
|                                         _ => normalized.clone(), |  | ||||||
|                                             } |                                             } | ||||||
|  |                                         }) | ||||||
|  |                                         .unwrap_or(ty) | ||||||
|                                 } |                                 } | ||||||
|                             } else { |                             } else { | ||||||
|                                 ty |                                 ty | ||||||
|  | @ -504,8 +478,8 @@ impl<'a> InferenceTable<'a> { | ||||||
|     pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { |     pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | ||||||
|         let var = self.new_type_var(); |         let var = self.new_type_var(); | ||||||
|         let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; |         let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; | ||||||
|         let obligation = alias_eq.cast(Interner); |         let obligation: Goal = alias_eq.cast(Interner); | ||||||
|         self.register_obligation(obligation); |         self.register_obligation(obligation.to_nextsolver(self.interner)); | ||||||
|         var |         var | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -575,7 +549,9 @@ impl<'a> InferenceTable<'a> { | ||||||
|         Substitution::from_iter( |         Substitution::from_iter( | ||||||
|             Interner, |             Interner, | ||||||
|             binders.iter().map(|kind| match &kind.kind { |             binders.iter().map(|kind| match &kind.kind { | ||||||
|                 chalk_ir::VariableKind::Ty(ty_variable_kind) => self.new_var(*ty_variable_kind, false).cast(Interner), |                 chalk_ir::VariableKind::Ty(ty_variable_kind) => { | ||||||
|  |                     self.new_var(*ty_variable_kind, false).cast(Interner) | ||||||
|  |                 } | ||||||
|                 chalk_ir::VariableKind::Lifetime => self.new_lifetime_var().cast(Interner), |                 chalk_ir::VariableKind::Lifetime => self.new_lifetime_var().cast(Interner), | ||||||
|                 chalk_ir::VariableKind::Const(ty) => self.new_const_var(ty.clone()).cast(Interner), |                 chalk_ir::VariableKind::Const(ty) => self.new_const_var(ty.clone()).cast(Interner), | ||||||
|             }), |             }), | ||||||
|  | @ -590,7 +566,10 @@ impl<'a> InferenceTable<'a> { | ||||||
|         subst.apply(canonical.value, Interner) |         subst.apply(canonical.value, Interner) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn instantiate_canonical_ns<T>(&mut self, canonical: rustc_type_ir::Canonical<DbInterner<'a>, T>) -> T |     pub(crate) fn instantiate_canonical_ns<T>( | ||||||
|  |         &mut self, | ||||||
|  |         canonical: rustc_type_ir::Canonical<DbInterner<'a>, T>, | ||||||
|  |     ) -> T | ||||||
|     where |     where | ||||||
|         T: rustc_type_ir::TypeFoldable<DbInterner<'a>>, |         T: rustc_type_ir::TypeFoldable<DbInterner<'a>>, | ||||||
|     { |     { | ||||||
|  | @ -605,7 +584,7 @@ impl<'a> InferenceTable<'a> { | ||||||
|     where |     where | ||||||
|         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>, |         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>, | ||||||
|     { |     { | ||||||
|         let mut var_stack = &mut vec![]; |         let var_stack = &mut vec![]; | ||||||
|         t.fold_with( |         t.fold_with( | ||||||
|             &mut resolve::Resolver { table: self, var_stack, fallback }, |             &mut resolve::Resolver { table: self, var_stack, fallback }, | ||||||
|             DebruijnIndex::INNERMOST, |             DebruijnIndex::INNERMOST, | ||||||
|  | @ -618,6 +597,7 @@ impl<'a> InferenceTable<'a> { | ||||||
|     { |     { | ||||||
|         let t = self.resolve_with_fallback(t, &|_, _, d, _| d); |         let t = self.resolve_with_fallback(t, &|_, _, d, _| d); | ||||||
|         let t = self.normalize_associated_types_in(t); |         let t = self.normalize_associated_types_in(t); | ||||||
|  |         // let t = self.resolve_opaque_tys_in(t);
 | ||||||
|         // Resolve again, because maybe normalization inserted infer vars.
 |         // Resolve again, because maybe normalization inserted infer vars.
 | ||||||
|         self.resolve_with_fallback(t, &|_, _, d, _| d) |         self.resolve_with_fallback(t, &|_, _, d, _| d) | ||||||
|     } |     } | ||||||
|  | @ -650,7 +630,7 @@ impl<'a> InferenceTable<'a> { | ||||||
|         } |         } | ||||||
|         let float_vars = self.infer_ctxt.inner.borrow_mut().float_unification_table().len(); |         let float_vars = self.infer_ctxt.inner.borrow_mut().float_unification_table().len(); | ||||||
|         for v in 0..float_vars { |         for v in 0..float_vars { | ||||||
|             let var = InferenceVar::from(v as u32).to_ty(Interner, TyVariableKind::Integer); |             let var = InferenceVar::from(v as u32).to_ty(Interner, TyVariableKind::Float); | ||||||
|             let maybe_resolved = self.resolve_ty_shallow(&var); |             let maybe_resolved = self.resolve_ty_shallow(&var); | ||||||
|             if let TyKind::InferenceVar(_, kind) = maybe_resolved.kind(Interner) { |             if let TyKind::InferenceVar(_, kind) = maybe_resolved.kind(Interner) { | ||||||
|                 // I don't think we can ever unify these vars with float vars, but keep this here for now
 |                 // I don't think we can ever unify these vars with float vars, but keep this here for now
 | ||||||
|  | @ -665,7 +645,11 @@ impl<'a> InferenceTable<'a> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that.
 |     /// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that.
 | ||||||
|     pub(crate) fn unify<T: ChalkToNextSolver<'a, U>, U: Relate<DbInterner<'a>>>(&mut self, ty1: &T, ty2: &T) -> bool { |     pub(crate) fn unify<T: ChalkToNextSolver<'a, U>, U: Relate<DbInterner<'a>>>( | ||||||
|  |         &mut self, | ||||||
|  |         ty1: &T, | ||||||
|  |         ty2: &T, | ||||||
|  |     ) -> bool { | ||||||
|         let result = match self.try_unify(ty1, ty2) { |         let result = match self.try_unify(ty1, ty2) { | ||||||
|             Ok(r) => r, |             Ok(r) => r, | ||||||
|             Err(_) => return false, |             Err(_) => return false, | ||||||
|  | @ -675,17 +659,17 @@ impl<'a> InferenceTable<'a> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Unify two relatable values (e.g. `Ty`) and check whether trait goals which arise from that could be fulfilled
 |     /// Unify two relatable values (e.g. `Ty`) and check whether trait goals which arise from that could be fulfilled
 | ||||||
|     pub(crate) fn unify_deeply<T: ChalkToNextSolver<'a, U>, U: Relate<DbInterner<'a>>>(&mut self, ty1: &T, ty2: &T) -> bool { |     pub(crate) fn unify_deeply<T: ChalkToNextSolver<'a, U>, U: Relate<DbInterner<'a>>>( | ||||||
|  |         &mut self, | ||||||
|  |         ty1: &T, | ||||||
|  |         ty2: &T, | ||||||
|  |     ) -> bool { | ||||||
|         let result = match self.try_unify(ty1, ty2) { |         let result = match self.try_unify(ty1, ty2) { | ||||||
|             Ok(r) => r, |             Ok(r) => r, | ||||||
|             Err(_) => return false, |             Err(_) => return false, | ||||||
|         }; |         }; | ||||||
|         result.goals.iter().all(|goal| { |         result.goals.into_iter().all(|goal| { | ||||||
|             let goal = goal.to_nextsolver(self.interner); |             matches!(next_trait_solve_in_ctxt(&self.infer_ctxt, goal), Ok((_, Certainty::Yes))) | ||||||
|             match next_trait_solve_in_ctxt(&self.infer_ctxt, goal) { |  | ||||||
|                 Ok((_, Certainty::Yes)) => true, |  | ||||||
|                 _ => false, |  | ||||||
|             } |  | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -695,20 +679,15 @@ impl<'a> InferenceTable<'a> { | ||||||
|         &mut self, |         &mut self, | ||||||
|         t1: &T, |         t1: &T, | ||||||
|         t2: &T, |         t2: &T, | ||||||
|     ) -> InferResult<()> { |     ) -> InferResult<'a, ()> { | ||||||
|         let param_env = self.trait_env.env.to_nextsolver(self.interner); |         let param_env = self.trait_env.env.to_nextsolver(self.interner); | ||||||
|         let lhs = t1.to_nextsolver(self.interner); |         let lhs = t1.to_nextsolver(self.interner); | ||||||
|         let rhs = t2.to_nextsolver(self.interner); |         let rhs = t2.to_nextsolver(self.interner); | ||||||
|         let variance = rustc_type_ir::Variance::Invariant; |         let variance = rustc_type_ir::Variance::Invariant; | ||||||
|         let span = crate::next_solver::Span::dummy(); |         let span = crate::next_solver::Span::dummy(); | ||||||
|         match self.infer_ctxt.relate(param_env, lhs, variance, rhs, span) { |         match self.infer_ctxt.relate(param_env, lhs, variance, rhs, span) { | ||||||
|             Ok(res) => { |             Ok(goals) => Ok(InferOk { goals, value: () }), | ||||||
|             let goals = res.into_iter().map(|g| ChalkToNextSolver::from_nextsolver(g, self.interner)).collect(); |             Err(_) => Err(TypeError), | ||||||
|                 Ok(InferOk { goals, value: () }) |  | ||||||
|             } |  | ||||||
|             Err(_) => { |  | ||||||
|                 Err(TypeError) |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -719,19 +698,75 @@ impl<'a> InferenceTable<'a> { | ||||||
|         if !ty.data(Interner).flags.intersects(chalk_ir::TypeFlags::HAS_FREE_LOCAL_NAMES) { |         if !ty.data(Interner).flags.intersects(chalk_ir::TypeFlags::HAS_FREE_LOCAL_NAMES) { | ||||||
|             return ty.clone(); |             return ty.clone(); | ||||||
|         } |         } | ||||||
|         self.resolve_obligations_as_possible(); |         self.infer_ctxt | ||||||
|         ChalkToNextSolver::from_nextsolver(self.infer_ctxt.resolve_vars_if_possible(ty.to_nextsolver(self.interner)), self.interner) |             .resolve_vars_if_possible(ty.to_nextsolver(self.interner)) | ||||||
|  |             .to_chalk(self.interner) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot { |     pub(crate) fn resolve_vars_with_obligations<T>(&mut self, t: T) -> T | ||||||
|  |     where | ||||||
|  |         T: rustc_type_ir::TypeFoldable<DbInterner<'a>>, | ||||||
|  |     { | ||||||
|  |         use rustc_type_ir::TypeVisitableExt; | ||||||
|  | 
 | ||||||
|  |         if !t.has_non_region_infer() { | ||||||
|  |             return t; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let t = self.infer_ctxt.resolve_vars_if_possible(t); | ||||||
|  | 
 | ||||||
|  |         if !t.has_non_region_infer() { | ||||||
|  |             return t; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         self.resolve_obligations_as_possible(); | ||||||
|  |         self.infer_ctxt.resolve_vars_if_possible(t) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub(crate) fn structurally_resolve_type(&mut self, ty: &Ty) -> Ty { | ||||||
|  |         if let TyKind::Alias(..) = ty.kind(Interner) { | ||||||
|  |             self.structurally_normalize_ty(ty) | ||||||
|  |         } else { | ||||||
|  |             self.resolve_vars_with_obligations(ty.to_nextsolver(self.interner)) | ||||||
|  |                 .to_chalk(self.interner) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn structurally_normalize_ty(&mut self, ty: &Ty) -> Ty { | ||||||
|  |         self.structurally_normalize_term(ty.to_nextsolver(self.interner).into()) | ||||||
|  |             .expect_ty() | ||||||
|  |             .to_chalk(self.interner) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn structurally_normalize_term(&mut self, term: Term<'a>) -> Term<'a> { | ||||||
|  |         if term.to_alias_term().is_none() { | ||||||
|  |             return term; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let new_infer = self.infer_ctxt.next_term_var_of_kind(term); | ||||||
|  | 
 | ||||||
|  |         self.register_obligation(Predicate::new( | ||||||
|  |             self.interner, | ||||||
|  |             Binder::dummy(PredicateKind::AliasRelate( | ||||||
|  |                 term, | ||||||
|  |                 new_infer, | ||||||
|  |                 AliasRelationDirection::Equate, | ||||||
|  |             )), | ||||||
|  |         )); | ||||||
|  |         self.resolve_obligations_as_possible(); | ||||||
|  |         let res = self.infer_ctxt.resolve_vars_if_possible(new_infer); | ||||||
|  |         if res == new_infer { term } else { res } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot<'a> { | ||||||
|         let ctxt_snapshot = self.infer_ctxt.start_snapshot(); |         let ctxt_snapshot = self.infer_ctxt.start_snapshot(); | ||||||
|         let diverging_tys = self.diverging_tys.clone(); |         let diverging_tys = self.diverging_tys.clone(); | ||||||
|         let pending_obligations = self.pending_obligations.clone(); |         let pending_obligations = self.pending_obligations.clone(); | ||||||
|         InferenceTableSnapshot {ctxt_snapshot, pending_obligations, diverging_tys } |         InferenceTableSnapshot { ctxt_snapshot, pending_obligations, diverging_tys } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[tracing::instrument(skip_all)] |     #[tracing::instrument(skip_all)] | ||||||
|     pub(crate) fn rollback_to(&mut self, snapshot: InferenceTableSnapshot) { |     pub(crate) fn rollback_to(&mut self, snapshot: InferenceTableSnapshot<'a>) { | ||||||
|         self.infer_ctxt.rollback_to(snapshot.ctxt_snapshot); |         self.infer_ctxt.rollback_to(snapshot.ctxt_snapshot); | ||||||
|         self.diverging_tys = snapshot.diverging_tys; |         self.diverging_tys = snapshot.diverging_tys; | ||||||
|         self.pending_obligations = snapshot.pending_obligations; |         self.pending_obligations = snapshot.pending_obligations; | ||||||
|  | @ -745,7 +780,10 @@ impl<'a> InferenceTable<'a> { | ||||||
|         result |         result | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn commit_if_ok<T, E>(&mut self, f: impl FnOnce(&mut InferenceTable<'_>) -> Result<T, E>) -> Result<T, E> { |     pub(crate) fn commit_if_ok<T, E>( | ||||||
|  |         &mut self, | ||||||
|  |         f: impl FnOnce(&mut InferenceTable<'_>) -> Result<T, E>, | ||||||
|  |     ) -> Result<T, E> { | ||||||
|         let snapshot = self.snapshot(); |         let snapshot = self.snapshot(); | ||||||
|         let result = f(self); |         let result = f(self); | ||||||
|         match result { |         match result { | ||||||
|  | @ -765,59 +803,31 @@ impl<'a> InferenceTable<'a> { | ||||||
|         let in_env = InEnvironment::new(&self.trait_env.env, goal); |         let in_env = InEnvironment::new(&self.trait_env.env, goal); | ||||||
|         let canonicalized = self.canonicalize(in_env.to_nextsolver(self.interner)); |         let canonicalized = self.canonicalize(in_env.to_nextsolver(self.interner)); | ||||||
| 
 | 
 | ||||||
|         next_trait_solve_canonical(self.db, self.trait_env.krate, self.trait_env.block, canonicalized) |         next_trait_solve_canonical_in_ctxt(&self.infer_ctxt, canonicalized) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[tracing::instrument(level = "debug", skip(self))] |     #[tracing::instrument(level = "debug", skip(self))] | ||||||
|     pub(crate) fn solve_obligation(&mut self, goal: Goal) -> Result<Certainty, NoSolution> { |     pub(crate) fn solve_obligation(&mut self, goal: Goal) -> Result<Certainty, NoSolution> { | ||||||
|         let goal = InEnvironment::new(&self.trait_env.env, goal); |         let goal = InEnvironment::new(&self.trait_env.env, goal); | ||||||
|         let Some(goal) = self.unify_opaque_instead_of_solve(goal) else { 
 |  | ||||||
|             return Ok(Certainty::Yes); |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         let goal = goal.to_nextsolver(self.interner); |         let goal = goal.to_nextsolver(self.interner); | ||||||
|         let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal); |         let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal); | ||||||
|         result.map(|m| m.1) |         result.map(|m| m.1) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn register_obligation(&mut self, goal: Goal) { |     pub(crate) fn register_obligation(&mut self, predicate: Predicate<'a>) { | ||||||
|         let in_env = InEnvironment::new(&self.trait_env.env, goal); |         let goal = next_solver::Goal { | ||||||
|         self.register_obligation_in_env(in_env) |             param_env: self.trait_env.env.to_nextsolver(self.interner), | ||||||
|     } |             predicate, | ||||||
| 
 |         }; | ||||||
|     // If this goal is an `AliasEq` for an opaque type, just unify instead of trying to solve (since the next-solver is lazy)
 |         self.register_obligation_in_env(goal) | ||||||
|     fn unify_opaque_instead_of_solve(&mut self, goal: InEnvironment<Goal>) -> Option<InEnvironment<Goal>> { |  | ||||||
|         match goal.goal.data(Interner) { |  | ||||||
|             chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds( |  | ||||||
|                 chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), |  | ||||||
|             )) => { |  | ||||||
|                 if ty.inference_var(Interner).is_some() { |  | ||||||
|                     match alias { |  | ||||||
|                         chalk_ir::AliasTy::Opaque(opaque) => { |  | ||||||
|                             if self.unify( |  | ||||||
|                                 &chalk_ir::TyKind::OpaqueType( |  | ||||||
|                                     opaque.opaque_ty_id, |  | ||||||
|                                     opaque.substitution.clone(), |  | ||||||
|                                 ) |  | ||||||
|                                 .intern(Interner), |  | ||||||
|                                 ty, |  | ||||||
|                             ) { |  | ||||||
|                                 return None; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                         _ => {} |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             _ => {} |  | ||||||
|         } |  | ||||||
|         Some(goal) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[tracing::instrument(level = "debug", skip(self))] |     #[tracing::instrument(level = "debug", skip(self))] | ||||||
|     fn register_obligation_in_env(&mut self, goal: InEnvironment<Goal>) { |     fn register_obligation_in_env( | ||||||
|         let Some(goal) = self.unify_opaque_instead_of_solve(goal) else { return }; |         &mut self, | ||||||
|         let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal.to_nextsolver(self.interner)); |         goal: next_solver::Goal<'a, next_solver::Predicate<'a>>, | ||||||
|  |     ) { | ||||||
|  |         let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal); | ||||||
|         tracing::debug!(?result); |         tracing::debug!(?result); | ||||||
|         match result { |         match result { | ||||||
|             Ok((_, Certainty::Yes)) => {} |             Ok((_, Certainty::Yes)) => {} | ||||||
|  | @ -828,7 +838,7 @@ impl<'a> InferenceTable<'a> { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn register_infer_ok<T>(&mut self, infer_ok: InferOk<T>) { |     pub(crate) fn register_infer_ok<T>(&mut self, infer_ok: InferOk<'a, T>) { | ||||||
|         infer_ok.goals.into_iter().for_each(|goal| self.register_obligation_in_env(goal)); |         infer_ok.goals.into_iter().for_each(|goal| self.register_obligation_in_env(goal)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -841,12 +851,7 @@ impl<'a> InferenceTable<'a> { | ||||||
|             for goal in obligations.drain(..) { |             for goal in obligations.drain(..) { | ||||||
|                 tracing::debug!(obligation = ?goal); |                 tracing::debug!(obligation = ?goal); | ||||||
| 
 | 
 | ||||||
|                 let Some(goal) = self.unify_opaque_instead_of_solve(goal) else { 
 |                 let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal); | ||||||
|                     changed = true; |  | ||||||
|                     continue; |  | ||||||
|                 }; |  | ||||||
| 
 |  | ||||||
|                 let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal.to_nextsolver(self.interner)); |  | ||||||
|                 let (has_changed, certainty) = match result { |                 let (has_changed, certainty) = match result { | ||||||
|                     Ok(result) => result, |                     Ok(result) => result, | ||||||
|                     Err(_) => { |                     Err(_) => { | ||||||
|  | @ -934,40 +939,6 @@ impl<'a> InferenceTable<'a> { | ||||||
|             .fold_with(&mut VarFudger { table: self, highest_known_var }, DebruijnIndex::INNERMOST) |             .fold_with(&mut VarFudger { table: self, highest_known_var }, DebruijnIndex::INNERMOST) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[tracing::instrument(level = "debug", skip(self))] |  | ||||||
|     fn try_resolve_obligation( |  | ||||||
|         &mut self, |  | ||||||
|         canonicalized: &Canonicalized<InEnvironment<Goal>>, |  | ||||||
|     ) -> NextTraitSolveResult { |  | ||||||
|         let solution = next_trait_solve( |  | ||||||
|             self.db, |  | ||||||
|             self.trait_env.krate, |  | ||||||
|             self.trait_env.block, |  | ||||||
|             canonicalized.value.clone(), |  | ||||||
|         ); |  | ||||||
| 
 |  | ||||||
|         tracing::debug!(?solution, ?canonicalized); |  | ||||||
|         match &solution { |  | ||||||
|             NextTraitSolveResult::Certain(v) => { |  | ||||||
|                 canonicalized.apply_solution( |  | ||||||
|                     self, |  | ||||||
|                     Canonical { |  | ||||||
|                         binders: v.binders.clone(), |  | ||||||
|                         // FIXME handle constraints
 |  | ||||||
|                         value: v.value.subst.clone(), |  | ||||||
|                     }, |  | ||||||
|                 ); |  | ||||||
|             } |  | ||||||
|             // ...so, should think about how to get some actually get some guidance here
 |  | ||||||
|             NextTraitSolveResult::Uncertain(v) => { |  | ||||||
|                 canonicalized.apply_solution(self, v.clone()); |  | ||||||
|             } |  | ||||||
|             NextTraitSolveResult::NoSolution => {} |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         solution |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub(crate) fn callable_sig( |     pub(crate) fn callable_sig( | ||||||
|         &mut self, |         &mut self, | ||||||
|         ty: &Ty, |         ty: &Ty, | ||||||
|  | @ -1027,7 +998,7 @@ impl<'a> InferenceTable<'a> { | ||||||
| 
 | 
 | ||||||
|             let goal: Goal = trait_ref.clone().cast(Interner); |             let goal: Goal = trait_ref.clone().cast(Interner); | ||||||
|             if !self.try_obligation(goal.clone()).no_solution() { |             if !self.try_obligation(goal.clone()).no_solution() { | ||||||
|                 self.register_obligation(goal); |                 self.register_obligation(goal.to_nextsolver(self.interner)); | ||||||
|                 let return_ty = self.normalize_projection_ty(projection); |                 let return_ty = self.normalize_projection_ty(projection); | ||||||
|                 for &fn_x in subtraits { |                 for &fn_x in subtraits { | ||||||
|                     let fn_x_trait = fn_x.get_id(self.db, krate)?; |                     let fn_x_trait = fn_x.get_id(self.db, krate)?; | ||||||
|  | @ -1067,7 +1038,7 @@ impl<'a> InferenceTable<'a> { | ||||||
|         match ty.kind(Interner) { |         match ty.kind(Interner) { | ||||||
|             TyKind::Error => self.new_type_var(), |             TyKind::Error => self.new_type_var(), | ||||||
|             TyKind::InferenceVar(..) => { |             TyKind::InferenceVar(..) => { | ||||||
|                 let ty_resolved = self.resolve_ty_shallow(&ty); |                 let ty_resolved = self.structurally_resolve_type(&ty); | ||||||
|                 if ty_resolved.is_unknown() { self.new_type_var() } else { ty } |                 if ty_resolved.is_unknown() { self.new_type_var() } else { ty } | ||||||
|             } |             } | ||||||
|             _ => ty, |             _ => ty, | ||||||
|  | @ -1165,7 +1136,9 @@ impl fmt::Debug for InferenceTable<'_> { | ||||||
| mod resolve { | mod resolve { | ||||||
|     use super::InferenceTable; |     use super::InferenceTable; | ||||||
|     use crate::{ |     use crate::{ | ||||||
|         next_solver::mapping::ChalkToNextSolver, ConcreteConst, Const, ConstData, ConstScalar, ConstValue, DebruijnIndex, GenericArg, InferenceVar, Interner, Lifetime, Ty, TyVariableKind, VariableKind |         ConcreteConst, Const, ConstData, ConstScalar, ConstValue, DebruijnIndex, GenericArg, | ||||||
|  |         InferenceVar, Interner, Lifetime, Ty, TyVariableKind, VariableKind, | ||||||
|  |         next_solver::mapping::NextSolverToChalk, | ||||||
|     }; |     }; | ||||||
|     use chalk_ir::{ |     use chalk_ir::{ | ||||||
|         cast::Cast, |         cast::Cast, | ||||||
|  | @ -1220,7 +1193,7 @@ mod resolve { | ||||||
|                             .clone(); |                             .clone(); | ||||||
|                     } |                     } | ||||||
|                     if let Ok(known_ty) = self.table.infer_ctxt.probe_ty_var(vid) { |                     if let Ok(known_ty) = self.table.infer_ctxt.probe_ty_var(vid) { | ||||||
|                         let known_ty: Ty = ChalkToNextSolver::from_nextsolver(known_ty, self.table.interner); |                         let known_ty: Ty = known_ty.to_chalk(self.table.interner); | ||||||
|                         // known_ty may contain other variables that are known by now
 |                         // known_ty may contain other variables that are known by now
 | ||||||
|                         self.var_stack.push((var, VarKind::Ty(kind))); |                         self.var_stack.push((var, VarKind::Ty(kind))); | ||||||
|                         let result = known_ty.fold_with(self, outer_binder); |                         let result = known_ty.fold_with(self, outer_binder); | ||||||
|  | @ -1234,7 +1207,13 @@ mod resolve { | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 TyVariableKind::Integer => { |                 TyVariableKind::Integer => { | ||||||
|                     let vid = self.table.infer_ctxt.inner.borrow_mut().int_unification_table().find(IntVid::from(var.index())); |                     let vid = self | ||||||
|  |                         .table | ||||||
|  |                         .infer_ctxt | ||||||
|  |                         .inner | ||||||
|  |                         .borrow_mut() | ||||||
|  |                         .int_unification_table() | ||||||
|  |                         .find(IntVid::from(var.index())); | ||||||
|                     let var = InferenceVar::from(vid.as_u32()); |                     let var = InferenceVar::from(vid.as_u32()); | ||||||
|                     if self.var_stack.contains(&(var, VarKind::Ty(kind))) { |                     if self.var_stack.contains(&(var, VarKind::Ty(kind))) { | ||||||
|                         // recursive type
 |                         // recursive type
 | ||||||
|  | @ -1244,7 +1223,7 @@ mod resolve { | ||||||
|                             .clone(); |                             .clone(); | ||||||
|                     } |                     } | ||||||
|                     if let Some(known_ty) = self.table.infer_ctxt.resolve_int_var(vid) { |                     if let Some(known_ty) = self.table.infer_ctxt.resolve_int_var(vid) { | ||||||
|                         let known_ty: Ty = ChalkToNextSolver::from_nextsolver(known_ty, self.table.interner); |                         let known_ty: Ty = known_ty.to_chalk(self.table.interner); | ||||||
|                         // known_ty may contain other variables that are known by now
 |                         // known_ty may contain other variables that are known by now
 | ||||||
|                         self.var_stack.push((var, VarKind::Ty(kind))); |                         self.var_stack.push((var, VarKind::Ty(kind))); | ||||||
|                         let result = known_ty.fold_with(self, outer_binder); |                         let result = known_ty.fold_with(self, outer_binder); | ||||||
|  | @ -1258,7 +1237,13 @@ mod resolve { | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 TyVariableKind::Float => { |                 TyVariableKind::Float => { | ||||||
|                     let vid = self.table.infer_ctxt.inner.borrow_mut().float_unification_table().find(FloatVid::from(var.index())); |                     let vid = self | ||||||
|  |                         .table | ||||||
|  |                         .infer_ctxt | ||||||
|  |                         .inner | ||||||
|  |                         .borrow_mut() | ||||||
|  |                         .float_unification_table() | ||||||
|  |                         .find(FloatVid::from(var.index())); | ||||||
|                     let var = InferenceVar::from(vid.as_u32()); |                     let var = InferenceVar::from(vid.as_u32()); | ||||||
|                     if self.var_stack.contains(&(var, VarKind::Ty(kind))) { |                     if self.var_stack.contains(&(var, VarKind::Ty(kind))) { | ||||||
|                         // recursive type
 |                         // recursive type
 | ||||||
|  | @ -1268,7 +1253,7 @@ mod resolve { | ||||||
|                             .clone(); |                             .clone(); | ||||||
|                     } |                     } | ||||||
|                     if let Some(known_ty) = self.table.infer_ctxt.resolve_float_var(vid) { |                     if let Some(known_ty) = self.table.infer_ctxt.resolve_float_var(vid) { | ||||||
|                         let known_ty: Ty = ChalkToNextSolver::from_nextsolver(known_ty, self.table.interner); |                         let known_ty: Ty = known_ty.to_chalk(self.table.interner); | ||||||
|                         // known_ty may contain other variables that are known by now
 |                         // known_ty may contain other variables that are known by now
 | ||||||
|                         self.var_stack.push((var, VarKind::Ty(kind))); |                         self.var_stack.push((var, VarKind::Ty(kind))); | ||||||
|                         let result = known_ty.fold_with(self, outer_binder); |                         let result = known_ty.fold_with(self, outer_binder); | ||||||
|  | @ -1290,7 +1275,10 @@ mod resolve { | ||||||
|             var: InferenceVar, |             var: InferenceVar, | ||||||
|             outer_binder: DebruijnIndex, |             outer_binder: DebruijnIndex, | ||||||
|         ) -> Const { |         ) -> Const { | ||||||
|             let vid = self.table.infer_ctxt.root_const_var(rustc_type_ir::ConstVid::from_u32(var.index())); |             let vid = self | ||||||
|  |                 .table | ||||||
|  |                 .infer_ctxt | ||||||
|  |                 .root_const_var(rustc_type_ir::ConstVid::from_u32(var.index())); | ||||||
|             let var = InferenceVar::from(vid.as_u32()); |             let var = InferenceVar::from(vid.as_u32()); | ||||||
|             let default = ConstData { |             let default = ConstData { | ||||||
|                 ty: ty.clone(), |                 ty: ty.clone(), | ||||||
|  | @ -1305,7 +1293,7 @@ mod resolve { | ||||||
|                     .clone(); |                     .clone(); | ||||||
|             } |             } | ||||||
|             if let Ok(known_const) = self.table.infer_ctxt.probe_const_var(vid) { |             if let Ok(known_const) = self.table.infer_ctxt.probe_const_var(vid) { | ||||||
|                 let known_const: Const = ChalkToNextSolver::from_nextsolver(known_const, self.table.interner); |                 let known_const: Const = known_const.to_chalk(self.table.interner); | ||||||
|                 // known_ty may contain other variables that are known by now
 |                 // known_ty may contain other variables that are known by now
 | ||||||
|                 self.var_stack.push((var, VarKind::Const)); |                 self.var_stack.push((var, VarKind::Const)); | ||||||
|                 let result = known_const.fold_with(self, outer_binder); |                 let result = known_const.fold_with(self, outer_binder); | ||||||
|  |  | ||||||
|  | @ -101,7 +101,10 @@ use crate::{ | ||||||
|     display::{DisplayTarget, HirDisplay}, |     display::{DisplayTarget, HirDisplay}, | ||||||
|     generics::Generics, |     generics::Generics, | ||||||
|     infer::unify::InferenceTable, |     infer::unify::InferenceTable, | ||||||
|     next_solver::{DbInterner, mapping::convert_ty_for_result}, |     next_solver::{ | ||||||
|  |         DbInterner, | ||||||
|  |         mapping::{ChalkToNextSolver, convert_ty_for_result}, | ||||||
|  |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| pub use autoderef::autoderef; | pub use autoderef::autoderef; | ||||||
|  | @ -957,8 +960,10 @@ pub fn callable_sig_from_fn_trait( | ||||||
|     ) |     ) | ||||||
|     .build(); |     .build(); | ||||||
| 
 | 
 | ||||||
|     if !table.try_obligation(trait_ref.clone().cast(Interner)).no_solution() { |     let goal: Goal = trait_ref.clone().cast(Interner); | ||||||
|         table.register_obligation(trait_ref.clone().cast(Interner)); |     let pred = goal.to_nextsolver(table.interner); | ||||||
|  |     if !table.try_obligation(goal).no_solution() { | ||||||
|  |         table.register_obligation(pred); | ||||||
|         let return_ty = table.normalize_projection_ty(projection); |         let return_ty = table.normalize_projection_ty(projection); | ||||||
|         for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] { |         for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] { | ||||||
|             let fn_x_trait = fn_x.get_id(db, krate)?; |             let fn_x_trait = fn_x.get_id(db, krate)?; | ||||||
|  |  | ||||||
|  | @ -22,7 +22,25 @@ use stdx::never; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     autoderef::{self, AutoderefKind}, db::HirDatabase, from_chalk_trait_id, from_foreign_def_id, infer::{unify::InferenceTable, Adjust, Adjustment, OverloadedDeref, PointerCast}, lang_items::is_box, next_solver::{mapping::ChalkToNextSolver, SolverDefId}, primitive::{FloatTy, IntTy, UintTy}, to_chalk_trait_id, traits::{next_trait_solve_canonical}, utils::all_super_traits, AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData, Goal, InEnvironment, Interner, Mutability, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind, VariableKind, WhereClause |     AdtId, AliasTy, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, | ||||||
|  |     GenericArgData, Goal, InEnvironment, Interner, Mutability, Scalar, Substitution, | ||||||
|  |     TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind, | ||||||
|  |     VariableKind, WhereClause, | ||||||
|  |     autoderef::{self, AutoderefKind}, | ||||||
|  |     db::HirDatabase, | ||||||
|  |     from_chalk_trait_id, from_foreign_def_id, | ||||||
|  |     infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable}, | ||||||
|  |     lang_items::is_box, | ||||||
|  |     next_solver::{ | ||||||
|  |         self, SolverDefId, | ||||||
|  |         fulfill::FulfillmentCtxt, | ||||||
|  |         infer::DefineOpaqueTypes, | ||||||
|  |         mapping::{ChalkToNextSolver, NextSolverToChalk}, | ||||||
|  |     }, | ||||||
|  |     primitive::{FloatTy, IntTy, UintTy}, | ||||||
|  |     to_chalk_trait_id, | ||||||
|  |     traits::next_trait_solve_canonical_in_ctxt, | ||||||
|  |     utils::all_super_traits, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// This is used as a key for indexing impls.
 | /// This is used as a key for indexing impls.
 | ||||||
|  | @ -89,6 +107,7 @@ impl TyFingerprint { | ||||||
|             } |             } | ||||||
|             TyKind::AssociatedType(_, _) |             TyKind::AssociatedType(_, _) | ||||||
|             | TyKind::OpaqueType(_, _) |             | TyKind::OpaqueType(_, _) | ||||||
|  |             | TyKind::Alias(AliasTy::Opaque(_)) | ||||||
|             | TyKind::FnDef(_, _) |             | TyKind::FnDef(_, _) | ||||||
|             | TyKind::Closure(_, _) |             | TyKind::Closure(_, _) | ||||||
|             | TyKind::Coroutine(..) |             | TyKind::Coroutine(..) | ||||||
|  | @ -106,7 +125,7 @@ impl TyFingerprint { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Creates a TyFingerprint for looking up a trait impl.
 |     /// Creates a TyFingerprint for looking up a trait impl.
 | ||||||
|     pub fn for_trait_impl_ns<'db>(ty: &crate::next_solver::Ty<'db>) -> Option<TyFingerprint> { |     pub fn for_trait_impl_ns<'db>(ty: &next_solver::Ty<'db>) -> Option<TyFingerprint> { | ||||||
|         use rustc_type_ir::TyKind; |         use rustc_type_ir::TyKind; | ||||||
|         let fp = match (*ty).kind() { |         let fp = match (*ty).kind() { | ||||||
|             TyKind::Str => TyFingerprint::Str, |             TyKind::Str => TyFingerprint::Str, | ||||||
|  | @ -523,7 +542,7 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma | ||||||
| /// Look up the method with the given name.
 | /// Look up the method with the given name.
 | ||||||
| pub(crate) fn lookup_method<'db>( | pub(crate) fn lookup_method<'db>( | ||||||
|     db: &'db dyn HirDatabase, |     db: &'db dyn HirDatabase, | ||||||
|     ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, |     ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | ||||||
|     env: Arc<TraitEnvironment>, |     env: Arc<TraitEnvironment>, | ||||||
|     traits_in_scope: &FxHashSet<TraitId>, |     traits_in_scope: &FxHashSet<TraitId>, | ||||||
|     visible_from_module: VisibleFromModule, |     visible_from_module: VisibleFromModule, | ||||||
|  | @ -605,7 +624,7 @@ pub struct ReceiverAdjustments { | ||||||
| 
 | 
 | ||||||
| impl ReceiverAdjustments { | impl ReceiverAdjustments { | ||||||
|     pub(crate) fn apply(&self, table: &mut InferenceTable<'_>, ty: Ty) -> (Ty, Vec<Adjustment>) { |     pub(crate) fn apply(&self, table: &mut InferenceTable<'_>, ty: Ty) -> (Ty, Vec<Adjustment>) { | ||||||
|         let mut ty = table.resolve_ty_shallow(&ty); |         let mut ty = table.structurally_resolve_type(&ty); | ||||||
|         let mut adjust = Vec::new(); |         let mut adjust = Vec::new(); | ||||||
|         for _ in 0..self.autoderefs { |         for _ in 0..self.autoderefs { | ||||||
|             match autoderef::autoderef_step(table, ty.clone(), true, false) { |             match autoderef::autoderef_step(table, ty.clone(), true, false) { | ||||||
|  | @ -686,7 +705,7 @@ impl ReceiverAdjustments { | ||||||
| // lifetime problems, because we need to borrow temp `CrateImplDefs`.
 | // lifetime problems, because we need to borrow temp `CrateImplDefs`.
 | ||||||
| // FIXME add a context type here?
 | // FIXME add a context type here?
 | ||||||
| pub(crate) fn iterate_method_candidates<'db, T>( | pub(crate) fn iterate_method_candidates<'db, T>( | ||||||
|     ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, |     ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | ||||||
|     db: &'db dyn HirDatabase, |     db: &'db dyn HirDatabase, | ||||||
|     env: Arc<TraitEnvironment>, |     env: Arc<TraitEnvironment>, | ||||||
|     traits_in_scope: &FxHashSet<TraitId>, |     traits_in_scope: &FxHashSet<TraitId>, | ||||||
|  | @ -887,7 +906,7 @@ fn find_matching_impl( | ||||||
|                 if table.try_obligation(goal.clone()).no_solution() { |                 if table.try_obligation(goal.clone()).no_solution() { | ||||||
|                     return None; |                     return None; | ||||||
|                 } |                 } | ||||||
|                 table.register_obligation(goal); |                 table.register_obligation(goal.to_nextsolver(table.interner)); | ||||||
|             } |             } | ||||||
|             Some((impl_.impl_items(db), table.resolve_completely(impl_substs))) |             Some((impl_.impl_items(db), table.resolve_completely(impl_substs))) | ||||||
|         }) |         }) | ||||||
|  | @ -1035,7 +1054,7 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn iterate_path_candidates<'db>( | pub fn iterate_path_candidates<'db>( | ||||||
|     ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, |     ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | ||||||
|     db: &'db dyn HirDatabase, |     db: &'db dyn HirDatabase, | ||||||
|     env: Arc<TraitEnvironment>, |     env: Arc<TraitEnvironment>, | ||||||
|     traits_in_scope: &FxHashSet<TraitId>, |     traits_in_scope: &FxHashSet<TraitId>, | ||||||
|  | @ -1057,7 +1076,7 @@ pub fn iterate_path_candidates<'db>( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn iterate_method_candidates_dyn<'db>( | pub fn iterate_method_candidates_dyn<'db>( | ||||||
|     ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, |     ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | ||||||
|     db: &'db dyn HirDatabase, |     db: &'db dyn HirDatabase, | ||||||
|     env: Arc<TraitEnvironment>, |     env: Arc<TraitEnvironment>, | ||||||
|     traits_in_scope: &FxHashSet<TraitId>, |     traits_in_scope: &FxHashSet<TraitId>, | ||||||
|  | @ -1096,7 +1115,7 @@ pub fn iterate_method_candidates_dyn<'db>( | ||||||
|             // types*.
 |             // types*.
 | ||||||
| 
 | 
 | ||||||
|             let mut table = InferenceTable::new(db, env); |             let mut table = InferenceTable::new(db, env); | ||||||
|             let ty = table.instantiate_canonical_ns(ty.clone()); |             let ty = table.instantiate_canonical_ns(*ty); | ||||||
|             let deref_chain = autoderef_method_receiver(&mut table, ty); |             let deref_chain = autoderef_method_receiver(&mut table, ty); | ||||||
| 
 | 
 | ||||||
|             deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| { |             deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| { | ||||||
|  | @ -1129,18 +1148,13 @@ pub fn iterate_method_candidates_dyn<'db>( | ||||||
| #[tracing::instrument(skip_all, fields(name = ?name))] | #[tracing::instrument(skip_all, fields(name = ?name))] | ||||||
| fn iterate_method_candidates_with_autoref<'db>( | fn iterate_method_candidates_with_autoref<'db>( | ||||||
|     table: &mut InferenceTable<'db>, |     table: &mut InferenceTable<'db>, | ||||||
|     receiver_ty: crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, |     receiver_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | ||||||
|     first_adjustment: ReceiverAdjustments, |     first_adjustment: ReceiverAdjustments, | ||||||
|     traits_in_scope: &FxHashSet<TraitId>, |     traits_in_scope: &FxHashSet<TraitId>, | ||||||
|     visible_from_module: VisibleFromModule, |     visible_from_module: VisibleFromModule, | ||||||
|     name: Option<&Name>, |     name: Option<&Name>, | ||||||
|     callback: &mut dyn MethodCandidateCallback, |     callback: &mut dyn MethodCandidateCallback, | ||||||
| ) -> ControlFlow<()> { | ) -> ControlFlow<()> { | ||||||
|     if matches!(receiver_ty.value.kind(), rustc_type_ir::TyKind::Bound(..)) { |  | ||||||
|         // don't try to resolve methods on unknown types
 |  | ||||||
|         return ControlFlow::Continue(()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     let interner = table.interner; |     let interner = table.interner; | ||||||
| 
 | 
 | ||||||
|     let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| { |     let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| { | ||||||
|  | @ -1166,12 +1180,17 @@ fn iterate_method_candidates_with_autoref<'db>( | ||||||
|         maybe_reborrowed.autoderefs += 1; |         maybe_reborrowed.autoderefs += 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     iterate_method_candidates_by_receiver(receiver_ty.clone(), maybe_reborrowed)?; |     iterate_method_candidates_by_receiver(receiver_ty, maybe_reborrowed)?; | ||||||
| 
 | 
 | ||||||
|     let refed = crate::next_solver::Canonical { |     let refed = next_solver::Canonical { | ||||||
|         max_universe: receiver_ty.max_universe, |         max_universe: receiver_ty.max_universe, | ||||||
|         variables: receiver_ty.variables, |         variables: receiver_ty.variables, | ||||||
|         value: crate::next_solver::Ty::new_ref(interner, crate::next_solver::Region::error(interner), receiver_ty.value, rustc_ast_ir::Mutability::Not), |         value: next_solver::Ty::new_ref( | ||||||
|  |             interner, | ||||||
|  |             next_solver::Region::error(interner), | ||||||
|  |             receiver_ty.value, | ||||||
|  |             rustc_ast_ir::Mutability::Not, | ||||||
|  |         ), | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     iterate_method_candidates_by_receiver( |     iterate_method_candidates_by_receiver( | ||||||
|  | @ -1179,10 +1198,15 @@ fn iterate_method_candidates_with_autoref<'db>( | ||||||
|         first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)), |         first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)), | ||||||
|     )?; |     )?; | ||||||
| 
 | 
 | ||||||
|     let ref_muted = crate::next_solver::Canonical { |     let ref_muted = next_solver::Canonical { | ||||||
|         max_universe: receiver_ty.max_universe, |         max_universe: receiver_ty.max_universe, | ||||||
|         variables: receiver_ty.variables, |         variables: receiver_ty.variables, | ||||||
|         value: crate::next_solver::Ty::new_ref(interner, crate::next_solver::Region::error(interner), receiver_ty.value, rustc_ast_ir::Mutability::Mut), |         value: next_solver::Ty::new_ref( | ||||||
|  |             interner, | ||||||
|  |             next_solver::Region::error(interner), | ||||||
|  |             receiver_ty.value, | ||||||
|  |             rustc_ast_ir::Mutability::Mut, | ||||||
|  |         ), | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     iterate_method_candidates_by_receiver( |     iterate_method_candidates_by_receiver( | ||||||
|  | @ -1190,10 +1214,12 @@ fn iterate_method_candidates_with_autoref<'db>( | ||||||
|         first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)), |         first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)), | ||||||
|     )?; |     )?; | ||||||
| 
 | 
 | ||||||
|     if let rustc_type_ir::TyKind::RawPtr(ty, rustc_ast_ir::Mutability::Mut) = receiver_ty.value.kind() { |     if let rustc_type_ir::TyKind::RawPtr(ty, rustc_ast_ir::Mutability::Mut) = | ||||||
|  |         receiver_ty.value.kind() | ||||||
|  |     { | ||||||
|         let const_ptr_ty = rustc_type_ir::Canonical { |         let const_ptr_ty = rustc_type_ir::Canonical { | ||||||
|             max_universe: rustc_type_ir::UniverseIndex::ZERO, |             max_universe: rustc_type_ir::UniverseIndex::ZERO, | ||||||
|             value: crate::next_solver::Ty::new_ptr(interner, ty, rustc_ast_ir::Mutability::Not), |             value: next_solver::Ty::new_ptr(interner, ty, rustc_ast_ir::Mutability::Not), | ||||||
|             variables: receiver_ty.variables, |             variables: receiver_ty.variables, | ||||||
|         }; |         }; | ||||||
|         iterate_method_candidates_by_receiver( |         iterate_method_candidates_by_receiver( | ||||||
|  | @ -1247,7 +1273,7 @@ where | ||||||
| #[tracing::instrument(skip_all, fields(name = ?name))] | #[tracing::instrument(skip_all, fields(name = ?name))] | ||||||
| fn iterate_method_candidates_by_receiver<'db>( | fn iterate_method_candidates_by_receiver<'db>( | ||||||
|     table: &mut InferenceTable<'db>, |     table: &mut InferenceTable<'db>, | ||||||
|     receiver_ty: crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, |     receiver_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | ||||||
|     receiver_adjustments: ReceiverAdjustments, |     receiver_adjustments: ReceiverAdjustments, | ||||||
|     traits_in_scope: &FxHashSet<TraitId>, |     traits_in_scope: &FxHashSet<TraitId>, | ||||||
|     visible_from_module: VisibleFromModule, |     visible_from_module: VisibleFromModule, | ||||||
|  | @ -1255,7 +1281,7 @@ fn iterate_method_candidates_by_receiver<'db>( | ||||||
|     callback: &mut dyn MethodCandidateCallback, |     callback: &mut dyn MethodCandidateCallback, | ||||||
| ) -> ControlFlow<()> { | ) -> ControlFlow<()> { | ||||||
|     let receiver_ty = table.instantiate_canonical_ns(receiver_ty); |     let receiver_ty = table.instantiate_canonical_ns(receiver_ty); | ||||||
|     let receiver_ty: crate::Ty = ChalkToNextSolver::from_nextsolver(receiver_ty, table.interner); |     let receiver_ty: crate::Ty = receiver_ty.to_chalk(table.interner); | ||||||
|     // We're looking for methods with *receiver* type receiver_ty. These could
 |     // We're looking for methods with *receiver* type receiver_ty. These could
 | ||||||
|     // be found in any of the derefs of receiver_ty, so we have to go through
 |     // be found in any of the derefs of receiver_ty, so we have to go through
 | ||||||
|     // that, including raw derefs.
 |     // that, including raw derefs.
 | ||||||
|  | @ -1270,6 +1296,7 @@ fn iterate_method_candidates_by_receiver<'db>( | ||||||
|                 Some(&receiver_ty), |                 Some(&receiver_ty), | ||||||
|                 Some(receiver_adjustments.clone()), |                 Some(receiver_adjustments.clone()), | ||||||
|                 visible_from_module, |                 visible_from_module, | ||||||
|  |                 LookupMode::MethodCall, | ||||||
|                 &mut |adjustments, item, is_visible| { |                 &mut |adjustments, item, is_visible| { | ||||||
|                     callback.on_inherent_method(adjustments, item, is_visible) |                     callback.on_inherent_method(adjustments, item, is_visible) | ||||||
|                 }, |                 }, | ||||||
|  | @ -1293,6 +1320,7 @@ fn iterate_method_candidates_by_receiver<'db>( | ||||||
|                 name, |                 name, | ||||||
|                 Some(&receiver_ty), |                 Some(&receiver_ty), | ||||||
|                 Some(receiver_adjustments.clone()), |                 Some(receiver_adjustments.clone()), | ||||||
|  |                 LookupMode::MethodCall, | ||||||
|                 &mut |adjustments, item, is_visible| { |                 &mut |adjustments, item, is_visible| { | ||||||
|                     callback.on_trait_method(adjustments, item, is_visible) |                     callback.on_trait_method(adjustments, item, is_visible) | ||||||
|                 }, |                 }, | ||||||
|  | @ -1304,7 +1332,7 @@ fn iterate_method_candidates_by_receiver<'db>( | ||||||
| 
 | 
 | ||||||
| #[tracing::instrument(skip_all, fields(name = ?name))] | #[tracing::instrument(skip_all, fields(name = ?name))] | ||||||
| fn iterate_method_candidates_for_self_ty<'db>( | fn iterate_method_candidates_for_self_ty<'db>( | ||||||
|     self_ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, |     self_ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | ||||||
|     db: &'db dyn HirDatabase, |     db: &'db dyn HirDatabase, | ||||||
|     env: Arc<TraitEnvironment>, |     env: Arc<TraitEnvironment>, | ||||||
|     traits_in_scope: &FxHashSet<TraitId>, |     traits_in_scope: &FxHashSet<TraitId>, | ||||||
|  | @ -1313,7 +1341,7 @@ fn iterate_method_candidates_for_self_ty<'db>( | ||||||
|     callback: &mut dyn MethodCandidateCallback, |     callback: &mut dyn MethodCandidateCallback, | ||||||
| ) -> ControlFlow<()> { | ) -> ControlFlow<()> { | ||||||
|     let mut table = InferenceTable::new(db, env); |     let mut table = InferenceTable::new(db, env); | ||||||
|     let self_ty = ChalkToNextSolver::from_nextsolver(table.instantiate_canonical_ns(self_ty.clone()), table.interner); |     let self_ty = table.instantiate_canonical_ns(*self_ty).to_chalk(table.interner); | ||||||
|     iterate_inherent_methods( |     iterate_inherent_methods( | ||||||
|         &self_ty, |         &self_ty, | ||||||
|         &mut table, |         &mut table, | ||||||
|  | @ -1321,6 +1349,7 @@ fn iterate_method_candidates_for_self_ty<'db>( | ||||||
|         None, |         None, | ||||||
|         None, |         None, | ||||||
|         visible_from_module, |         visible_from_module, | ||||||
|  |         LookupMode::Path, | ||||||
|         &mut |adjustments, item, is_visible| { |         &mut |adjustments, item, is_visible| { | ||||||
|             callback.on_inherent_method(adjustments, item, is_visible) |             callback.on_inherent_method(adjustments, item, is_visible) | ||||||
|         }, |         }, | ||||||
|  | @ -1332,6 +1361,7 @@ fn iterate_method_candidates_for_self_ty<'db>( | ||||||
|         name, |         name, | ||||||
|         None, |         None, | ||||||
|         None, |         None, | ||||||
|  |         LookupMode::Path, | ||||||
|         &mut |adjustments, item, is_visible| { |         &mut |adjustments, item, is_visible| { | ||||||
|             callback.on_trait_method(adjustments, item, is_visible) |             callback.on_trait_method(adjustments, item, is_visible) | ||||||
|         }, |         }, | ||||||
|  | @ -1346,12 +1376,13 @@ fn iterate_trait_method_candidates( | ||||||
|     name: Option<&Name>, |     name: Option<&Name>, | ||||||
|     receiver_ty: Option<&Ty>, |     receiver_ty: Option<&Ty>, | ||||||
|     receiver_adjustments: Option<ReceiverAdjustments>, |     receiver_adjustments: Option<ReceiverAdjustments>, | ||||||
|  |     mode: LookupMode, | ||||||
|     callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, |     callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, | ||||||
| ) -> ControlFlow<()> { | ) -> ControlFlow<()> { | ||||||
|     let db = table.db; |     let db = table.db; | ||||||
| 
 | 
 | ||||||
|     let canonical_self_ty = ChalkToNextSolver::from_nextsolver(table.canonicalize(self_ty.clone().to_nextsolver(table.interner)), table.interner); |     let canonical_self_ty = table.canonicalize(self_ty.clone().to_nextsolver(table.interner)); | ||||||
|     let TraitEnvironment { krate, block, .. } = *table.trait_env; |     let TraitEnvironment { krate, .. } = *table.trait_env; | ||||||
| 
 | 
 | ||||||
|     'traits: for &t in traits_in_scope { |     'traits: for &t in traits_in_scope { | ||||||
|         let data = db.trait_signature(t); |         let data = db.trait_signature(t); | ||||||
|  | @ -1391,15 +1422,22 @@ fn iterate_trait_method_candidates( | ||||||
|         for &(_, item) in t.trait_items(db).items.iter() { |         for &(_, item) in t.trait_items(db).items.iter() { | ||||||
|             // Don't pass a `visible_from_module` down to `is_valid_candidate`,
 |             // Don't pass a `visible_from_module` down to `is_valid_candidate`,
 | ||||||
|             // since only inherent methods should be included into visibility checking.
 |             // since only inherent methods should be included into visibility checking.
 | ||||||
|             let visible = |             let visible = match is_valid_trait_method_candidate( | ||||||
|                 match is_valid_trait_method_candidate(table, t, name, receiver_ty, item, self_ty) { |                 table, | ||||||
|  |                 t, | ||||||
|  |                 name, | ||||||
|  |                 receiver_ty, | ||||||
|  |                 item, | ||||||
|  |                 self_ty, | ||||||
|  |                 mode, | ||||||
|  |             ) { | ||||||
|                 IsValidCandidate::Yes => true, |                 IsValidCandidate::Yes => true, | ||||||
|                 IsValidCandidate::NotVisible => false, |                 IsValidCandidate::NotVisible => false, | ||||||
|                 IsValidCandidate::No => continue, |                 IsValidCandidate::No => continue, | ||||||
|             }; |             }; | ||||||
|             if !known_implemented { |             if !known_implemented { | ||||||
|                 let goal = generic_implements_goal(db, &table.trait_env, t, &canonical_self_ty); |                 let goal = generic_implements_goal_ns(table, t, canonical_self_ty); | ||||||
|                 if db.trait_solve(krate, block, goal.cast(Interner)).no_solution() { |                 if next_trait_solve_canonical_in_ctxt(&table.infer_ctxt, goal).no_solution() { | ||||||
|                     continue 'traits; |                     continue 'traits; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -1418,6 +1456,7 @@ fn iterate_inherent_methods( | ||||||
|     receiver_ty: Option<&Ty>, |     receiver_ty: Option<&Ty>, | ||||||
|     receiver_adjustments: Option<ReceiverAdjustments>, |     receiver_adjustments: Option<ReceiverAdjustments>, | ||||||
|     visible_from_module: VisibleFromModule, |     visible_from_module: VisibleFromModule, | ||||||
|  |     mode: LookupMode, | ||||||
|     callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, |     callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, | ||||||
| ) -> ControlFlow<()> { | ) -> ControlFlow<()> { | ||||||
|     let db = table.db; |     let db = table.db; | ||||||
|  | @ -1441,6 +1480,7 @@ fn iterate_inherent_methods( | ||||||
|                 receiver_adjustments.clone(), |                 receiver_adjustments.clone(), | ||||||
|                 callback, |                 callback, | ||||||
|                 traits, |                 traits, | ||||||
|  |                 mode, | ||||||
|             )?; |             )?; | ||||||
|         } |         } | ||||||
|         TyKind::Dyn(_) => { |         TyKind::Dyn(_) => { | ||||||
|  | @ -1454,6 +1494,7 @@ fn iterate_inherent_methods( | ||||||
|                     receiver_adjustments.clone(), |                     receiver_adjustments.clone(), | ||||||
|                     callback, |                     callback, | ||||||
|                     traits.into_iter(), |                     traits.into_iter(), | ||||||
|  |                     mode, | ||||||
|                 )?; |                 )?; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -1512,6 +1553,7 @@ fn iterate_inherent_methods( | ||||||
|         receiver_adjustments: Option<ReceiverAdjustments>, |         receiver_adjustments: Option<ReceiverAdjustments>, | ||||||
|         callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, |         callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, | ||||||
|         traits: impl Iterator<Item = TraitId>, |         traits: impl Iterator<Item = TraitId>, | ||||||
|  |         mode: LookupMode, | ||||||
|     ) -> ControlFlow<()> { |     ) -> ControlFlow<()> { | ||||||
|         let db = table.db; |         let db = table.db; | ||||||
|         for t in traits { |         for t in traits { | ||||||
|  | @ -1525,6 +1567,7 @@ fn iterate_inherent_methods( | ||||||
|                     receiver_ty, |                     receiver_ty, | ||||||
|                     item, |                     item, | ||||||
|                     self_ty, |                     self_ty, | ||||||
|  |                     mode, | ||||||
|                 ) { |                 ) { | ||||||
|                     IsValidCandidate::Yes => true, |                     IsValidCandidate::Yes => true, | ||||||
|                     IsValidCandidate::NotVisible => false, |                     IsValidCandidate::NotVisible => false, | ||||||
|  | @ -1571,22 +1614,17 @@ fn iterate_inherent_methods( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Returns the receiver type for the index trait call.
 | /// Returns the receiver type for the index trait call.
 | ||||||
| pub(crate) fn resolve_indexing_op( | pub(crate) fn resolve_indexing_op<'db>( | ||||||
|     db: &dyn HirDatabase, |     table: &mut InferenceTable<'db>, | ||||||
|     env: Arc<TraitEnvironment>, |     ty: next_solver::Canonical<'db, next_solver::Ty<'db>>, | ||||||
|     ty: Canonical<Ty>, |  | ||||||
|     index_trait: TraitId, |     index_trait: TraitId, | ||||||
| ) -> Option<ReceiverAdjustments> { | ) -> Option<ReceiverAdjustments> { | ||||||
|     let mut table = InferenceTable::new(db, env); |     let ty = table.instantiate_canonical_ns(ty); | ||||||
|     let ty = table.instantiate_canonical(ty); |     let deref_chain = autoderef_method_receiver(table, ty); | ||||||
|     let interner = table.interner; |  | ||||||
|     let deref_chain = autoderef_method_receiver(&mut table, ty.to_nextsolver(interner)); |  | ||||||
|     for (ty, adj) in deref_chain { |     for (ty, adj) in deref_chain { | ||||||
|         //let goal = generic_implements_goal_ns(db, &table.trait_env, index_trait, &ty);
 |         //let goal = generic_implements_goal_ns(db, &table.trait_env, index_trait, &ty);
 | ||||||
|         let goal = generic_implements_goal(db, &table.trait_env, index_trait, &ChalkToNextSolver::from_nextsolver(ty, interner)); |         let goal = generic_implements_goal_ns(table, index_trait, ty); | ||||||
|         let goal: chalk_ir::Canonical<chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>> = goal.cast(Interner); |         if !next_trait_solve_canonical_in_ctxt(&table.infer_ctxt, goal).no_solution() { | ||||||
|         let goal = goal.to_nextsolver(interner); |  | ||||||
|         if !next_trait_solve_canonical(db, table.trait_env.krate, table.trait_env.block, goal).no_solution() { |  | ||||||
|             return Some(adj); |             return Some(adj); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -1666,6 +1704,7 @@ fn is_valid_trait_method_candidate( | ||||||
|     receiver_ty: Option<&Ty>, |     receiver_ty: Option<&Ty>, | ||||||
|     item: AssocItemId, |     item: AssocItemId, | ||||||
|     self_ty: &Ty, |     self_ty: &Ty, | ||||||
|  |     mode: LookupMode, | ||||||
| ) -> IsValidCandidate { | ) -> IsValidCandidate { | ||||||
|     let db = table.db; |     let db = table.db; | ||||||
|     match item { |     match item { | ||||||
|  | @ -1693,6 +1732,35 @@ fn is_valid_trait_method_candidate( | ||||||
|                     let expected_receiver = |                     let expected_receiver = | ||||||
|                         sig.map(|s| s.params()[0].clone()).substitute(Interner, &fn_subst); |                         sig.map(|s| s.params()[0].clone()).substitute(Interner, &fn_subst); | ||||||
| 
 | 
 | ||||||
|  |                     // FIXME: Clean up this mess with some context struct like rustc's `ProbeContext`
 | ||||||
|  |                     let variance = match mode { | ||||||
|  |                         LookupMode::MethodCall => rustc_type_ir::Variance::Covariant, | ||||||
|  |                         LookupMode::Path => rustc_type_ir::Variance::Invariant, | ||||||
|  |                     }; | ||||||
|  |                     let res = table | ||||||
|  |                         .infer_ctxt | ||||||
|  |                         .at( | ||||||
|  |                             &next_solver::infer::traits::ObligationCause::dummy(), | ||||||
|  |                             table.trait_env.env.to_nextsolver(table.interner), | ||||||
|  |                         ) | ||||||
|  |                         .relate( | ||||||
|  |                             DefineOpaqueTypes::No, | ||||||
|  |                             expected_receiver.to_nextsolver(table.interner), | ||||||
|  |                             variance, | ||||||
|  |                             receiver_ty.to_nextsolver(table.interner), | ||||||
|  |                         ); | ||||||
|  |                     let Ok(infer_ok) = res else { | ||||||
|  |                         return IsValidCandidate::No; | ||||||
|  |                     }; | ||||||
|  | 
 | ||||||
|  |                     if !infer_ok.obligations.is_empty() { | ||||||
|  |                         let mut ctxt = FulfillmentCtxt::new(&table.infer_ctxt); | ||||||
|  |                         for pred in infer_ok.into_obligations() { | ||||||
|  |                             ctxt.register_predicate_obligation(&table.infer_ctxt, pred); | ||||||
|  |                         } | ||||||
|  |                         check_that!(ctxt.select_all_or_error(&table.infer_ctxt).is_empty()); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|                     check_that!(table.unify(receiver_ty, &expected_receiver)); |                     check_that!(table.unify(receiver_ty, &expected_receiver)); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -1839,53 +1907,36 @@ fn generic_implements_goal( | ||||||
|     Canonical { binders, value } |     Canonical { binders, value } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* |  | ||||||
| /// This creates Substs for a trait with the given Self type and type variables
 | /// This creates Substs for a trait with the given Self type and type variables
 | ||||||
| /// for all other parameters, to query the trait solver with it.
 | /// for all other parameters, to query the trait solver with it.
 | ||||||
| #[tracing::instrument(skip_all)] | #[tracing::instrument(skip_all)] | ||||||
| fn generic_implements_goal_ns<'db>( | fn generic_implements_goal_ns<'db>( | ||||||
|     db: &'db dyn HirDatabase, |     table: &mut InferenceTable<'db>, | ||||||
|     interner: DbInterner<'db>, |  | ||||||
|     env: &TraitEnvironment, |  | ||||||
|     trait_: TraitId, |     trait_: TraitId, | ||||||
|     self_ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, |     self_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | ||||||
| ) -> crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, crate::next_solver::Predicate<'db>>> { | ) -> next_solver::Canonical<'db, next_solver::Goal<'db, crate::next_solver::Predicate<'db>>> { | ||||||
|     let variables = self_ty.variables; |     let args = table.infer_ctxt.fresh_args_for_item(SolverDefId::TraitId(trait_)); | ||||||
|     let trait_ref = TyBuilder::trait_ref(db, trait_) |     let self_ty = table.instantiate_canonical_ns(self_ty); | ||||||
|         .push(ChalkToNextSolver::from_nextsolver(self_ty.value, interner)) |     let trait_ref = | ||||||
|         .fill_with_bound_vars(DebruijnIndex::INNERMOST, variables.len()) |         rustc_type_ir::TraitRef::new_from_args(table.infer_ctxt.interner, trait_.into(), args) | ||||||
|         .build(); |             .with_replaced_self_ty(table.infer_ctxt.interner, self_ty); | ||||||
|  |     let goal = next_solver::Goal::new( | ||||||
|  |         table.infer_ctxt.interner, | ||||||
|  |         table.trait_env.env.to_nextsolver(table.infer_ctxt.interner), | ||||||
|  |         trait_ref, | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     let infer_ctxt = interner.infer_ctxt().build(TypingMode::non_body_analysis()); |     table.canonicalize(goal) | ||||||
|     let args = infer_ctxt.fresh_args_for_item(SolverDefId::TraitId(trait_)); |  | ||||||
| 
 |  | ||||||
|     rustc_type_ir::TraitRef::new(interner, SolverDefId::TraitId(trait_)).with_self_ty(interner, self_ty.value); |  | ||||||
|     
 |  | ||||||
| 
 |  | ||||||
|     let kinds = |  | ||||||
|         binders.iter().cloned().chain(trait_ref.substitution.iter(Interner).skip(1).map(|it| { |  | ||||||
|             let vk = match it.data(Interner) { |  | ||||||
|                 GenericArgData::Ty(_) => VariableKind::Ty(chalk_ir::TyVariableKind::General), |  | ||||||
|                 GenericArgData::Lifetime(_) => VariableKind::Lifetime, |  | ||||||
|                 GenericArgData::Const(c) => VariableKind::Const(c.data(Interner).ty.clone()), |  | ||||||
|             }; |  | ||||||
|             WithKind::new(vk, UniverseIndex::ROOT) |  | ||||||
|         })); |  | ||||||
|     let binders = CanonicalVarKinds::from_iter(Interner, kinds); |  | ||||||
| 
 |  | ||||||
|     let obligation = trait_ref.cast(Interner); |  | ||||||
|     let value = InEnvironment::new(&env.env, obligation); |  | ||||||
|     crate::next_solver::Canonical { max_universe, value, variables } |  | ||||||
| } | } | ||||||
| */ |  | ||||||
| 
 | 
 | ||||||
| fn autoderef_method_receiver<'db>( | fn autoderef_method_receiver<'db>( | ||||||
|     table: &mut InferenceTable<'db>, |     table: &mut InferenceTable<'db>, | ||||||
|     ty: crate::next_solver::Ty<'db>, |     ty: next_solver::Ty<'db>, | ||||||
| ) -> Vec<(crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ReceiverAdjustments)> { | ) -> Vec<(next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ReceiverAdjustments)> { | ||||||
|     let interner = table.interner; |     let interner = table.interner; | ||||||
|     let mut deref_chain = Vec::new(); |     let mut deref_chain = Vec::new(); | ||||||
|     let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ChalkToNextSolver::from_nextsolver(ty, interner), false, true); |     let mut autoderef = | ||||||
|  |         autoderef::Autoderef::new_no_tracking(table, ty.to_chalk(interner), false, true); | ||||||
|     while let Some((ty, derefs)) = autoderef.next() { |     while let Some((ty, derefs)) = autoderef.next() { | ||||||
|         deref_chain.push(( |         deref_chain.push(( | ||||||
|             autoderef.table.canonicalize(ty.to_nextsolver(interner)), |             autoderef.table.canonicalize(ty.to_nextsolver(interner)), | ||||||
|  | @ -1894,11 +1945,11 @@ fn autoderef_method_receiver<'db>( | ||||||
|     } |     } | ||||||
|     // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
 |     // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
 | ||||||
|     if let Some((rustc_type_ir::Array(parameters, _), variables, max_universe, adj)) = |     if let Some((rustc_type_ir::Array(parameters, _), variables, max_universe, adj)) = | ||||||
|         deref_chain.last().map(|d| (d.0.value.kind(), d.0.variables.clone(), d.0.max_universe, d.1.clone())) |         deref_chain.last().map(|d| (d.0.value.kind(), d.0.variables, d.0.max_universe, d.1.clone())) | ||||||
|     { |     { | ||||||
|         let unsized_ty = crate::next_solver::Ty::new_slice(interner, parameters); |         let unsized_ty = next_solver::Ty::new_slice(interner, parameters); | ||||||
|         deref_chain.push(( |         deref_chain.push(( | ||||||
|             crate::next_solver::Canonical { max_universe, value: unsized_ty, variables, }, |             next_solver::Canonical { max_universe, value: unsized_ty, variables }, | ||||||
|             ReceiverAdjustments { unsize_array: true, ..adj.clone() }, |             ReceiverAdjustments { unsize_array: true, ..adj.clone() }, | ||||||
|         )); |         )); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -34,8 +34,7 @@ pub use eval::{ | ||||||
| }; | }; | ||||||
| pub use lower::{MirLowerError, lower_to_mir, mir_body_for_closure_query, mir_body_query}; | pub use lower::{MirLowerError, lower_to_mir, mir_body_for_closure_query, mir_body_query}; | ||||||
| pub use monomorphization::{ | pub use monomorphization::{ | ||||||
|     monomorphize_mir_body_bad, monomorphized_mir_body_for_closure_query, |     monomorphized_mir_body_for_closure_query, monomorphized_mir_body_query, | ||||||
|     monomorphized_mir_body_query, |  | ||||||
| }; | }; | ||||||
| use rustc_hash::FxHashMap; | use rustc_hash::FxHashMap; | ||||||
| use smallvec::{SmallVec, smallvec}; | use smallvec::{SmallVec, smallvec}; | ||||||
|  |  | ||||||
|  | @ -38,7 +38,6 @@ struct Filler<'a> { | ||||||
|     trait_env: Arc<TraitEnvironment>, |     trait_env: Arc<TraitEnvironment>, | ||||||
|     subst: &'a Substitution, |     subst: &'a Substitution, | ||||||
|     generics: Option<Generics>, |     generics: Option<Generics>, | ||||||
|     owner: DefWithBodyId, |  | ||||||
| } | } | ||||||
| impl FallibleTypeFolder<Interner> for Filler<'_> { | impl FallibleTypeFolder<Interner> for Filler<'_> { | ||||||
|     type Error = MirLowerError; |     type Error = MirLowerError; | ||||||
|  | @ -66,7 +65,11 @@ impl FallibleTypeFolder<Interner> for Filler<'_> { | ||||||
|                 })) |                 })) | ||||||
|                 .intern(Interner)) |                 .intern(Interner)) | ||||||
|             } |             } | ||||||
|             TyKind::OpaqueType(id, subst) => { |             TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { | ||||||
|  |                 opaque_ty_id: id, | ||||||
|  |                 substitution: subst, | ||||||
|  |             })) | ||||||
|  |             | TyKind::OpaqueType(id, subst) => { | ||||||
|                 let impl_trait_id = self.db.lookup_intern_impl_trait_id((*id).into()); |                 let impl_trait_id = self.db.lookup_intern_impl_trait_id((*id).into()); | ||||||
|                 let subst = subst.clone().try_fold_with(self.as_dyn(), outer_binder)?; |                 let subst = subst.clone().try_fold_with(self.as_dyn(), outer_binder)?; | ||||||
|                 match impl_trait_id { |                 match impl_trait_id { | ||||||
|  | @ -74,7 +77,6 @@ impl FallibleTypeFolder<Interner> for Filler<'_> { | ||||||
|                         let infer = self.db.infer(func.into()); |                         let infer = self.db.infer(func.into()); | ||||||
|                         let filler = &mut Filler { |                         let filler = &mut Filler { | ||||||
|                             db: self.db, |                             db: self.db, | ||||||
|                             owner: self.owner, |  | ||||||
|                             trait_env: self.trait_env.clone(), |                             trait_env: self.trait_env.clone(), | ||||||
|                             subst: &subst, |                             subst: &subst, | ||||||
|                             generics: Some(generics(self.db, func.into())), |                             generics: Some(generics(self.db, func.into())), | ||||||
|  | @ -306,7 +308,7 @@ pub fn monomorphized_mir_body_query( | ||||||
|     trait_env: Arc<crate::TraitEnvironment>, |     trait_env: Arc<crate::TraitEnvironment>, | ||||||
| ) -> Result<Arc<MirBody>, MirLowerError> { | ) -> Result<Arc<MirBody>, MirLowerError> { | ||||||
|     let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def)); |     let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def)); | ||||||
|     let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner }; |     let filler = &mut Filler { db, subst: &subst, trait_env, generics }; | ||||||
|     let body = db.mir_body(owner)?; |     let body = db.mir_body(owner)?; | ||||||
|     let mut body = (*body).clone(); |     let mut body = (*body).clone(); | ||||||
|     filler.fill_body(&mut body)?; |     filler.fill_body(&mut body)?; | ||||||
|  | @ -330,23 +332,9 @@ pub fn monomorphized_mir_body_for_closure_query( | ||||||
| ) -> Result<Arc<MirBody>, MirLowerError> { | ) -> Result<Arc<MirBody>, MirLowerError> { | ||||||
|     let InternedClosure(owner, _) = db.lookup_intern_closure(closure); |     let InternedClosure(owner, _) = db.lookup_intern_closure(closure); | ||||||
|     let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def)); |     let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def)); | ||||||
|     let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner }; |     let filler = &mut Filler { db, subst: &subst, trait_env, generics }; | ||||||
|     let body = db.mir_body_for_closure(closure)?; |     let body = db.mir_body_for_closure(closure)?; | ||||||
|     let mut body = (*body).clone(); |     let mut body = (*body).clone(); | ||||||
|     filler.fill_body(&mut body)?; |     filler.fill_body(&mut body)?; | ||||||
|     Ok(Arc::new(body)) |     Ok(Arc::new(body)) | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // FIXME: remove this function. Monomorphization is a time consuming job and should always be a query.
 |  | ||||||
| pub fn monomorphize_mir_body_bad( |  | ||||||
|     db: &dyn HirDatabase, |  | ||||||
|     mut body: MirBody, |  | ||||||
|     subst: Substitution, |  | ||||||
|     trait_env: Arc<crate::TraitEnvironment>, |  | ||||||
| ) -> Result<MirBody, MirLowerError> { |  | ||||||
|     let owner = body.owner; |  | ||||||
|     let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def)); |  | ||||||
|     let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner }; |  | ||||||
|     filler.fill_body(&mut body)?; |  | ||||||
|     Ok(body) |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -5,11 +5,10 @@ pub mod abi; | ||||||
| mod consts; | mod consts; | ||||||
| mod def_id; | mod def_id; | ||||||
| pub mod fold; | pub mod fold; | ||||||
| mod fulfill; | pub mod fulfill; | ||||||
| mod generic_arg; | mod generic_arg; | ||||||
| pub mod generics; | pub mod generics; | ||||||
| pub mod infer; | pub mod infer; | ||||||
| //mod infer_new;
 |  | ||||||
| pub mod interner; | pub mod interner; | ||||||
| mod ir_print; | mod ir_print; | ||||||
| pub mod mapping; | pub mod mapping; | ||||||
|  | @ -24,7 +23,6 @@ pub mod util; | ||||||
| pub use consts::*; | pub use consts::*; | ||||||
| pub use def_id::*; | pub use def_id::*; | ||||||
| pub use generic_arg::*; | pub use generic_arg::*; | ||||||
| //pub use infer_new::*;
 |  | ||||||
| pub use interner::*; | pub use interner::*; | ||||||
| pub use opaques::*; | pub use opaques::*; | ||||||
| pub use predicate::*; | pub use predicate::*; | ||||||
|  |  | ||||||
|  | @ -1,14 +1,28 @@ | ||||||
|  | //! This module contains code to canonicalize values into a `Canonical<'db, T>`.
 | ||||||
|  | //!
 | ||||||
|  | //! For an overview of what canonicalization is and how it fits into
 | ||||||
|  | //! rustc, check out the [chapter in the rustc dev guide][c].
 | ||||||
|  | //!
 | ||||||
|  | //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
 | ||||||
| 
 | 
 | ||||||
| use rustc_hash::FxHashMap; | use rustc_hash::FxHashMap; | ||||||
| use rustc_index::Idx; | use rustc_index::Idx; | ||||||
| use rustc_type_ir::inherent::{Const as _, IntoKind as _, Region as _, SliceLike, Ty as _}; |  | ||||||
| use rustc_type_ir::InferTy::{self, FloatVar, IntVar, TyVar}; | use rustc_type_ir::InferTy::{self, FloatVar, IntVar, TyVar}; | ||||||
| use rustc_type_ir::{BoundVar, CanonicalQueryInput, CanonicalTyVarKind, DebruijnIndex, Flags, InferConst, RegionKind, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UniverseIndex}; | use rustc_type_ir::inherent::{Const as _, IntoKind as _, Region as _, SliceLike, Ty as _}; | ||||||
|  | use rustc_type_ir::{ | ||||||
|  |     BoundVar, CanonicalQueryInput, CanonicalTyVarKind, DebruijnIndex, Flags, InferConst, | ||||||
|  |     RegionKind, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, | ||||||
|  |     UniverseIndex, | ||||||
|  | }; | ||||||
| use smallvec::SmallVec; | use smallvec::SmallVec; | ||||||
| use tracing::debug; | use tracing::debug; | ||||||
| 
 | 
 | ||||||
| use crate::next_solver::infer::InferCtxt; | use crate::next_solver::infer::InferCtxt; | ||||||
| use crate::next_solver::{Binder, BoundRegion, BoundRegionKind, BoundTy, Canonical, CanonicalVarKind, CanonicalVars, Const, ConstKind, DbInterner, GenericArg, ParamEnvAnd, Placeholder, Region, Ty, TyKind}; | use crate::next_solver::{ | ||||||
|  |     Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, Canonical, CanonicalVarKind, | ||||||
|  |     CanonicalVars, Const, ConstKind, DbInterner, GenericArg, ParamEnvAnd, Placeholder, Region, Ty, | ||||||
|  |     TyKind, | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| /// When we canonicalize a value to form a query, we wind up replacing
 | /// When we canonicalize a value to form a query, we wind up replacing
 | ||||||
| /// various parts of it with canonical variables. This struct stores
 | /// various parts of it with canonical variables. This struct stores
 | ||||||
|  | @ -65,7 +79,7 @@ impl<'db> InferCtxt<'db> { | ||||||
|         // `param_env` because they are treated differently by trait selection.
 |         // `param_env` because they are treated differently by trait selection.
 | ||||||
|         let canonical_param_env = Canonicalizer::canonicalize( |         let canonical_param_env = Canonicalizer::canonicalize( | ||||||
|             param_env, |             param_env, | ||||||
|             None, |             self, | ||||||
|             self.interner, |             self.interner, | ||||||
|             &CanonicalizeFreeRegionsOtherThanStatic, |             &CanonicalizeFreeRegionsOtherThanStatic, | ||||||
|             query_state, |             query_state, | ||||||
|  | @ -74,7 +88,7 @@ impl<'db> InferCtxt<'db> { | ||||||
|         let canonical = Canonicalizer::canonicalize_with_base( |         let canonical = Canonicalizer::canonicalize_with_base( | ||||||
|             canonical_param_env, |             canonical_param_env, | ||||||
|             value, |             value, | ||||||
|             Some(self), |             self, | ||||||
|             self.interner, |             self.interner, | ||||||
|             &CanonicalizeAllFreeRegions, |             &CanonicalizeAllFreeRegions, | ||||||
|             query_state, |             query_state, | ||||||
|  | @ -115,7 +129,7 @@ impl<'db> InferCtxt<'db> { | ||||||
|         let mut query_state = OriginalQueryValues::default(); |         let mut query_state = OriginalQueryValues::default(); | ||||||
|         Canonicalizer::canonicalize( |         Canonicalizer::canonicalize( | ||||||
|             value, |             value, | ||||||
|             Some(self), |             self, | ||||||
|             self.interner, |             self.interner, | ||||||
|             &CanonicalizeQueryResponse, |             &CanonicalizeQueryResponse, | ||||||
|             &mut query_state, |             &mut query_state, | ||||||
|  | @ -129,7 +143,7 @@ impl<'db> InferCtxt<'db> { | ||||||
|         let mut query_state = OriginalQueryValues::default(); |         let mut query_state = OriginalQueryValues::default(); | ||||||
|         Canonicalizer::canonicalize( |         Canonicalizer::canonicalize( | ||||||
|             value, |             value, | ||||||
|             Some(self), |             self, | ||||||
|             self.interner, |             self.interner, | ||||||
|             &CanonicalizeUserTypeAnnotation, |             &CanonicalizeUserTypeAnnotation, | ||||||
|             &mut query_state, |             &mut query_state, | ||||||
|  | @ -165,7 +179,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { | ||||||
|         canonicalizer: &mut Canonicalizer<'_, 'db>, |         canonicalizer: &mut Canonicalizer<'_, 'db>, | ||||||
|         mut r: Region<'db>, |         mut r: Region<'db>, | ||||||
|     ) -> Region<'db> { |     ) -> Region<'db> { | ||||||
|         let infcx = canonicalizer.infcx.unwrap(); |         let infcx = canonicalizer.infcx; | ||||||
| 
 | 
 | ||||||
|         if let RegionKind::ReVar(vid) = r.kind() { |         if let RegionKind::ReVar(vid) = r.kind() { | ||||||
|             r = infcx |             r = infcx | ||||||
|  | @ -180,12 +194,14 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         match r.kind() { |         match r.kind() { | ||||||
|             RegionKind::ReLateParam(_) | RegionKind::ReErased | RegionKind::ReStatic | RegionKind::ReEarlyParam(..) | RegionKind::ReError(..) => r, |             RegionKind::ReLateParam(_) | ||||||
|  |             | RegionKind::ReErased | ||||||
|  |             | RegionKind::ReStatic | ||||||
|  |             | RegionKind::ReEarlyParam(..) | ||||||
|  |             | RegionKind::ReError(..) => r, | ||||||
| 
 | 
 | ||||||
|             RegionKind::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region( |             RegionKind::RePlaceholder(placeholder) => canonicalizer | ||||||
|                 CanonicalVarKind::PlaceholderRegion(placeholder), |                 .canonical_var_for_region(CanonicalVarKind::PlaceholderRegion(placeholder), r), | ||||||
|                 r, |  | ||||||
|             ), |  | ||||||
| 
 | 
 | ||||||
|             RegionKind::ReVar(vid) => { |             RegionKind::ReVar(vid) => { | ||||||
|                 let universe = infcx |                 let universe = infcx | ||||||
|  | @ -194,10 +210,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { | ||||||
|                     .unwrap_region_constraints() |                     .unwrap_region_constraints() | ||||||
|                     .probe_value(vid) |                     .probe_value(vid) | ||||||
|                     .unwrap_err(); |                     .unwrap_err(); | ||||||
|                 canonicalizer.canonical_var_for_region( |                 canonicalizer.canonical_var_for_region(CanonicalVarKind::Region(universe), r) | ||||||
|                     CanonicalVarKind::Region(universe), |  | ||||||
|                     r, |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             _ => { |             _ => { | ||||||
|  | @ -240,7 +253,7 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation { | ||||||
|             RegionKind::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r), |             RegionKind::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r), | ||||||
|             RegionKind::RePlaceholder(..) | RegionKind::ReBound(..) => { |             RegionKind::RePlaceholder(..) | RegionKind::ReBound(..) => { | ||||||
|                 // We only expect region names that the user can type.
 |                 // We only expect region names that the user can type.
 | ||||||
|                 panic!("unexpected region in query response: `{:?}`", r) |                 panic!("unexpected region in query response: `{r:?}`") | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -296,7 +309,7 @@ impl CanonicalizeMode for CanonicalizeFreeRegionsOtherThanStatic { | ||||||
| 
 | 
 | ||||||
| struct Canonicalizer<'cx, 'db> { | struct Canonicalizer<'cx, 'db> { | ||||||
|     /// Set to `None` to disable the resolution of inference variables.
 |     /// Set to `None` to disable the resolution of inference variables.
 | ||||||
|     infcx: Option<&'cx InferCtxt<'db>>, |     infcx: &'cx InferCtxt<'db>, | ||||||
|     tcx: DbInterner<'db>, |     tcx: DbInterner<'db>, | ||||||
|     variables: SmallVec<[CanonicalVarKind<'db>; 8]>, |     variables: SmallVec<[CanonicalVarKind<'db>; 8]>, | ||||||
|     query_state: &'cx mut OriginalQueryValues<'db>, |     query_state: &'cx mut OriginalQueryValues<'db>, | ||||||
|  | @ -350,14 +363,14 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> { | ||||||
|                 // We need to canonicalize the *root* of our ty var.
 |                 // We need to canonicalize the *root* of our ty var.
 | ||||||
|                 // This is so that our canonical response correctly reflects
 |                 // This is so that our canonical response correctly reflects
 | ||||||
|                 // any equated inference vars correctly!
 |                 // any equated inference vars correctly!
 | ||||||
|                 let root_vid = self.infcx.unwrap().root_var(vid); |                 let root_vid = self.infcx.root_var(vid); | ||||||
|                 if root_vid != vid { |                 if root_vid != vid { | ||||||
|                     t = Ty::new_var(self.tcx, root_vid); |                     t = Ty::new_var(self.tcx, root_vid); | ||||||
|                     vid = root_vid; |                     vid = root_vid; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 debug!("canonical: type var found with vid {:?}", vid); |                 debug!("canonical: type var found with vid {:?}", vid); | ||||||
|                 match self.infcx.unwrap().probe_ty_var(vid) { |                 match self.infcx.probe_ty_var(vid) { | ||||||
|                     // `t` could be a float / int variable; canonicalize that instead.
 |                     // `t` could be a float / int variable; canonicalize that instead.
 | ||||||
|                     Ok(t) => { |                     Ok(t) => { | ||||||
|                         debug!("(resolved to {:?})", t); |                         debug!("(resolved to {:?})", t); | ||||||
|  | @ -380,29 +393,25 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> { | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             TyKind::Infer(IntVar(vid)) => { |             TyKind::Infer(IntVar(vid)) => { | ||||||
|                 let nt = self.infcx.unwrap().opportunistic_resolve_int_var(vid); |                 let nt = self.infcx.opportunistic_resolve_int_var(vid); | ||||||
|                 if nt != t { |                 if nt != t { | ||||||
|                     return self.fold_ty(nt); |                     self.fold_ty(nt) | ||||||
|                 } else { |                 } else { | ||||||
|                     self.canonicalize_ty_var( |                     self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Int), t) | ||||||
|                         CanonicalVarKind::Ty(CanonicalTyVarKind::Int), |  | ||||||
|                         t, |  | ||||||
|                     ) |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             TyKind::Infer(FloatVar(vid)) => { |             TyKind::Infer(FloatVar(vid)) => { | ||||||
|                 let nt = self.infcx.unwrap().opportunistic_resolve_float_var(vid); |                 let nt = self.infcx.opportunistic_resolve_float_var(vid); | ||||||
|                 if nt != t { |                 if nt != t { | ||||||
|                     return self.fold_ty(nt); |                     self.fold_ty(nt) | ||||||
|                 } else { |                 } else { | ||||||
|                     self.canonicalize_ty_var( |                     self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Float), t) | ||||||
|                         CanonicalVarKind::Ty(CanonicalTyVarKind::Float), |  | ||||||
|                         t, |  | ||||||
|                     ) |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             TyKind::Infer(InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_)) => { |             TyKind::Infer( | ||||||
|  |                 InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_), | ||||||
|  |             ) => { | ||||||
|                 panic!("encountered a fresh type during canonicalization") |                 panic!("encountered a fresh type during canonicalization") | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -410,10 +419,7 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> { | ||||||
|                 if !self.canonicalize_mode.preserve_universes() { |                 if !self.canonicalize_mode.preserve_universes() { | ||||||
|                     placeholder.universe = UniverseIndex::ROOT; |                     placeholder.universe = UniverseIndex::ROOT; | ||||||
|                 } |                 } | ||||||
|                 self.canonicalize_ty_var( |                 self.canonicalize_ty_var(CanonicalVarKind::PlaceholderTy(placeholder), t) | ||||||
|                     CanonicalVarKind::PlaceholderTy(placeholder), |  | ||||||
|                     t, |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             TyKind::Bound(debruijn, _) => { |             TyKind::Bound(debruijn, _) => { | ||||||
|  | @ -465,14 +471,14 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> { | ||||||
|                 // We need to canonicalize the *root* of our const var.
 |                 // We need to canonicalize the *root* of our const var.
 | ||||||
|                 // This is so that our canonical response correctly reflects
 |                 // This is so that our canonical response correctly reflects
 | ||||||
|                 // any equated inference vars correctly!
 |                 // any equated inference vars correctly!
 | ||||||
|                 let root_vid = self.infcx.unwrap().root_const_var(vid); |                 let root_vid = self.infcx.root_const_var(vid); | ||||||
|                 if root_vid != vid { |                 if root_vid != vid { | ||||||
|                     ct = Const::new_var(self.tcx, root_vid); |                     ct = Const::new_var(self.tcx, root_vid); | ||||||
|                     vid = root_vid; |                     vid = root_vid; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 debug!("canonical: const var found with vid {:?}", vid); |                 debug!("canonical: const var found with vid {:?}", vid); | ||||||
|                 match self.infcx.unwrap().probe_const_var(vid) { |                 match self.infcx.probe_const_var(vid) { | ||||||
|                     Ok(c) => { |                     Ok(c) => { | ||||||
|                         debug!("(resolved to {:?})", c); |                         debug!("(resolved to {:?})", c); | ||||||
|                         return self.fold_const(c); |                         return self.fold_const(c); | ||||||
|  | @ -485,10 +491,7 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> { | ||||||
|                             // FIXME: perf problem described in #55921.
 |                             // FIXME: perf problem described in #55921.
 | ||||||
|                             ui = UniverseIndex::ROOT; |                             ui = UniverseIndex::ROOT; | ||||||
|                         } |                         } | ||||||
|                         return self.canonicalize_const_var( |                         return self.canonicalize_const_var(CanonicalVarKind::Const(ui), ct); | ||||||
|                             CanonicalVarKind::Const(ui), |  | ||||||
|                             ct, |  | ||||||
|                         ); |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -503,10 +506,8 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             ConstKind::Placeholder(placeholder) => { |             ConstKind::Placeholder(placeholder) => { | ||||||
|                 return self.canonicalize_const_var( |                 return self | ||||||
|                     CanonicalVarKind::PlaceholderConst(placeholder), |                     .canonicalize_const_var(CanonicalVarKind::PlaceholderConst(placeholder), ct); | ||||||
|                     ct, |  | ||||||
|                 ); |  | ||||||
|             } |             } | ||||||
|             _ => {} |             _ => {} | ||||||
|         } |         } | ||||||
|  | @ -524,7 +525,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> { | ||||||
|     /// `canonicalize_query` and `canonicalize_response`.
 |     /// `canonicalize_query` and `canonicalize_response`.
 | ||||||
|     fn canonicalize<V>( |     fn canonicalize<V>( | ||||||
|         value: V, |         value: V, | ||||||
|         infcx: Option<&InferCtxt<'db>>, |         infcx: &InferCtxt<'db>, | ||||||
|         tcx: DbInterner<'db>, |         tcx: DbInterner<'db>, | ||||||
|         canonicalize_region_mode: &dyn CanonicalizeMode, |         canonicalize_region_mode: &dyn CanonicalizeMode, | ||||||
|         query_state: &mut OriginalQueryValues<'db>, |         query_state: &mut OriginalQueryValues<'db>, | ||||||
|  | @ -551,7 +552,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> { | ||||||
|     fn canonicalize_with_base<U, V>( |     fn canonicalize_with_base<U, V>( | ||||||
|         base: Canonical<'db, U>, |         base: Canonical<'db, U>, | ||||||
|         value: V, |         value: V, | ||||||
|         infcx: Option<&InferCtxt<'db>>, |         infcx: &InferCtxt<'db>, | ||||||
|         tcx: DbInterner<'db>, |         tcx: DbInterner<'db>, | ||||||
|         canonicalize_region_mode: &dyn CanonicalizeMode, |         canonicalize_region_mode: &dyn CanonicalizeMode, | ||||||
|         query_state: &mut OriginalQueryValues<'db>, |         query_state: &mut OriginalQueryValues<'db>, | ||||||
|  | @ -596,7 +597,8 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> { | ||||||
|         // anymore.
 |         // anymore.
 | ||||||
|         debug_assert!(!out_value.has_infer() && !out_value.has_placeholders()); |         debug_assert!(!out_value.has_infer() && !out_value.has_placeholders()); | ||||||
| 
 | 
 | ||||||
|         let canonical_variables = CanonicalVars::new_from_iter(tcx, canonicalizer.universe_canonicalized_variables()); |         let canonical_variables = | ||||||
|  |             CanonicalVars::new_from_iter(tcx, canonicalizer.universe_canonicalized_variables()); | ||||||
| 
 | 
 | ||||||
|         let max_universe = canonical_variables |         let max_universe = canonical_variables | ||||||
|             .iter() |             .iter() | ||||||
|  | @ -690,15 +692,11 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> { | ||||||
|         self.variables |         self.variables | ||||||
|             .iter() |             .iter() | ||||||
|             .map(|v| match *v { |             .map(|v| match *v { | ||||||
|                 CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => { |                 CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => *v, | ||||||
|                     return *v; |  | ||||||
|                 } |  | ||||||
|                 CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => { |                 CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => { | ||||||
|                     CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u])) |                     CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u])) | ||||||
|                 } |                 } | ||||||
|                 CanonicalVarKind::Region(u) => { |                 CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]), | ||||||
|                     CanonicalVarKind::Region(reverse_universe_map[&u]) |  | ||||||
|                 } |  | ||||||
|                 CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]), |                 CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]), | ||||||
|                 CanonicalVarKind::PlaceholderTy(placeholder) => { |                 CanonicalVarKind::PlaceholderTy(placeholder) => { | ||||||
|                     CanonicalVarKind::PlaceholderTy(Placeholder { |                     CanonicalVarKind::PlaceholderTy(Placeholder { | ||||||
|  | @ -735,14 +733,8 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> { | ||||||
|     ///
 |     ///
 | ||||||
|     /// (This works because unification never fails -- and hence trait
 |     /// (This works because unification never fails -- and hence trait
 | ||||||
|     /// selection is never affected -- due to a universe mismatch.)
 |     /// selection is never affected -- due to a universe mismatch.)
 | ||||||
|     fn canonical_var_for_region_in_root_universe( |     fn canonical_var_for_region_in_root_universe(&mut self, r: Region<'db>) -> Region<'db> { | ||||||
|         &mut self, |         self.canonical_var_for_region(CanonicalVarKind::Region(UniverseIndex::ROOT), r) | ||||||
|         r: Region<'db>, |  | ||||||
|     ) -> Region<'db> { |  | ||||||
|         self.canonical_var_for_region( |  | ||||||
|             CanonicalVarKind::Region(UniverseIndex::ROOT), |  | ||||||
|             r, |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Creates a canonical variable (with the given `info`)
 |     /// Creates a canonical variable (with the given `info`)
 | ||||||
|  | @ -762,9 +754,13 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> { | ||||||
|     /// *that*. Otherwise, create a new canonical variable for
 |     /// *that*. Otherwise, create a new canonical variable for
 | ||||||
|     /// `ty_var`.
 |     /// `ty_var`.
 | ||||||
|     fn canonicalize_ty_var(&mut self, info: CanonicalVarKind<'db>, ty_var: Ty<'db>) -> Ty<'db> { |     fn canonicalize_ty_var(&mut self, info: CanonicalVarKind<'db>, ty_var: Ty<'db>) -> Ty<'db> { | ||||||
|         debug_assert!(!self.infcx.is_some_and(|infcx| ty_var != infcx.shallow_resolve(ty_var))); |         debug_assert_eq!(ty_var, self.infcx.shallow_resolve(ty_var)); | ||||||
|         let var = self.canonical_var(info, ty_var.into()); |         let var = self.canonical_var(info, ty_var.into()); | ||||||
|         Ty::new_bound(self.tcx, self.binder_index, BoundTy { kind: crate::next_solver::BoundTyKind::Anon, var }) |         Ty::new_bound( | ||||||
|  |             self.tcx, | ||||||
|  |             self.binder_index, | ||||||
|  |             BoundTy { kind: crate::next_solver::BoundTyKind::Anon, var }, | ||||||
|  |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Given a type variable `const_var` of the given kind, first check
 |     /// Given a type variable `const_var` of the given kind, first check
 | ||||||
|  | @ -776,10 +772,8 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> { | ||||||
|         info: CanonicalVarKind<'db>, |         info: CanonicalVarKind<'db>, | ||||||
|         const_var: Const<'db>, |         const_var: Const<'db>, | ||||||
|     ) -> Const<'db> { |     ) -> Const<'db> { | ||||||
|         debug_assert!( |         debug_assert_eq!(const_var, self.infcx.shallow_resolve_const(const_var)); | ||||||
|             !self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var)) |  | ||||||
|         ); |  | ||||||
|         let var = self.canonical_var(info, const_var.into()); |         let var = self.canonical_var(info, const_var.into()); | ||||||
|         Const::new_bound(self.tcx, self.binder_index, var) |         Const::new_bound(self.tcx, self.binder_index, BoundConst { var }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -503,7 +503,10 @@ impl<'db> InferCtxt<'db> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn next_ty_vid(&self) -> TyVid { |     pub fn next_ty_vid(&self) -> TyVid { | ||||||
|         self.inner.borrow_mut().type_variables().new_var(self.universe(), TypeVariableOrigin { param_def_id: None }) |         self.inner | ||||||
|  |             .borrow_mut() | ||||||
|  |             .type_variables() | ||||||
|  |             .new_var(self.universe(), TypeVariableOrigin { param_def_id: None }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'db> { |     pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'db> { | ||||||
|  | @ -526,11 +529,13 @@ impl<'db> InferCtxt<'db> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn next_const_vid(&self) -> ConstVid { |     pub fn next_const_vid(&self) -> ConstVid { | ||||||
|         self |         self.inner | ||||||
|             .inner |  | ||||||
|             .borrow_mut() |             .borrow_mut() | ||||||
|             .const_unification_table() |             .const_unification_table() | ||||||
|             .new_key(ConstVariableValue::Unknown { origin: ConstVariableOrigin { param_def_id: None }, universe: self.universe() }) |             .new_key(ConstVariableValue::Unknown { | ||||||
|  |                 origin: ConstVariableOrigin { param_def_id: None }, | ||||||
|  |                 universe: self.universe(), | ||||||
|  |             }) | ||||||
|             .vid |             .vid | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -566,9 +571,7 @@ impl<'db> InferCtxt<'db> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn next_float_var(&self) -> Ty<'db> { |     pub fn next_float_var(&self) -> Ty<'db> { | ||||||
|         let next_float_var_id = |         Ty::new_float_var(self.interner, self.next_float_vid()) | ||||||
|             self.inner.borrow_mut().float_unification_table().new_key(FloatVarValue::Unknown); |  | ||||||
|         Ty::new_float_var(self.interner, next_float_var_id) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn next_float_vid(&self) -> FloatVid { |     pub fn next_float_vid(&self) -> FloatVid { | ||||||
|  | @ -815,9 +818,7 @@ impl<'db> InferCtxt<'db> { | ||||||
|         match value { |         match value { | ||||||
|             IntVarValue::IntType(ty) => Some(Ty::new_int(self.interner, ty)), |             IntVarValue::IntType(ty) => Some(Ty::new_int(self.interner, ty)), | ||||||
|             IntVarValue::UintType(ty) => Some(Ty::new_uint(self.interner, ty)), |             IntVarValue::UintType(ty) => Some(Ty::new_uint(self.interner, ty)), | ||||||
|             IntVarValue::Unknown => { |             IntVarValue::Unknown => None, | ||||||
|                 None |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -839,9 +840,7 @@ impl<'db> InferCtxt<'db> { | ||||||
|         let value = inner.float_unification_table().probe_value(vid); |         let value = inner.float_unification_table().probe_value(vid); | ||||||
|         match value { |         match value { | ||||||
|             FloatVarValue::Known(ty) => Some(Ty::new_float(self.interner, ty)), |             FloatVarValue::Known(ty) => Some(Ty::new_float(self.interner, ty)), | ||||||
|             FloatVarValue::Unknown => { |             FloatVarValue::Unknown => None, | ||||||
|                 None |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -9,12 +9,12 @@ use rustc_type_ir::{ | ||||||
|     solve::{Certainty, NoSolution}, |     solve::{Certainty, NoSolution}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | use crate::next_solver::mapping::NextSolverToChalk; | ||||||
| use crate::{ | use crate::{ | ||||||
|     TraitRefExt, |     TraitRefExt, | ||||||
|     db::HirDatabase, |     db::HirDatabase, | ||||||
|     next_solver::{ |     next_solver::{ | ||||||
|         ClauseKind, CoercePredicate, PredicateKind, SubtypePredicate, |         ClauseKind, CoercePredicate, PredicateKind, SubtypePredicate, mapping::ChalkToNextSolver, | ||||||
|         mapping::ChalkToNextSolver, |  | ||||||
|         util::sizedness_fast_path, |         util::sizedness_fast_path, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
|  | @ -200,7 +200,7 @@ impl<'db> SolverDelegate for SolverContext<'db> { | ||||||
|             SolverDefId::StaticId(c) => GeneralConstId::StaticId(c), |             SolverDefId::StaticId(c) => GeneralConstId::StaticId(c), | ||||||
|             _ => unreachable!(), |             _ => unreachable!(), | ||||||
|         }; |         }; | ||||||
|         let subst = ChalkToNextSolver::from_nextsolver(uv.args, self.interner); |         let subst = uv.args.to_chalk(self.interner); | ||||||
|         let ec = self.cx().db.const_eval(c, subst, None).ok()?; |         let ec = self.cx().db.const_eval(c, subst, None).ok()?; | ||||||
|         Some(ec.to_nextsolver(self.interner)) |         Some(ec.to_nextsolver(self.interner)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -49,7 +49,7 @@ fn let_stmt_coerce() { | ||||||
| //- minicore: coerce_unsized
 | //- minicore: coerce_unsized
 | ||||||
| fn test() { | fn test() { | ||||||
|     let x: &[isize] = &[1]; |     let x: &[isize] = &[1]; | ||||||
|                    // ^^^^ adjustments: Deref(None), Borrow(Ref('?2, Not)), Pointer(Unsize)
 |                    // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize)
 | ||||||
|     let x: *const [isize] = &[1]; |     let x: *const [isize] = &[1]; | ||||||
|                          // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
 |                          // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
 | ||||||
| } | } | ||||||
|  | @ -96,7 +96,7 @@ fn foo<T>(x: &[T]) -> &[T] { x } | ||||||
| fn test() { | fn test() { | ||||||
|     let x = if true { |     let x = if true { | ||||||
|         foo(&[1]) |         foo(&[1]) | ||||||
|          // ^^^^ adjustments: Deref(None), Borrow(Ref('?11, Not)), Pointer(Unsize)
 |          // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize)
 | ||||||
|     } else { |     } else { | ||||||
|         &[1] |         &[1] | ||||||
|     }; |     }; | ||||||
|  | @ -148,7 +148,7 @@ fn foo<T>(x: &[T]) -> &[T] { x } | ||||||
| fn test(i: i32) { | fn test(i: i32) { | ||||||
|     let x = match i { |     let x = match i { | ||||||
|         2 => foo(&[2]), |         2 => foo(&[2]), | ||||||
|               // ^^^^ adjustments: Deref(None), Borrow(Ref('?11, Not)), Pointer(Unsize)
 |               // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize)
 | ||||||
|         1 => &[1], |         1 => &[1], | ||||||
|         _ => &[3], |         _ => &[3], | ||||||
|     }; |     }; | ||||||
|  | @ -881,7 +881,7 @@ fn adjust_index() { | ||||||
| fn test() { | fn test() { | ||||||
|     let x = [1, 2, 3]; |     let x = [1, 2, 3]; | ||||||
|     x[2] = 6; |     x[2] = 6; | ||||||
|  // ^ adjustments: Borrow(Ref('?8, Mut))
 |  // ^ adjustments: Borrow(Ref('?0, Mut))
 | ||||||
| } | } | ||||||
|     ",
 |     ",
 | ||||||
|     ); |     ); | ||||||
|  | @ -906,11 +906,11 @@ impl core::ops::IndexMut<usize> for StructMut { | ||||||
| } | } | ||||||
| fn test() { | fn test() { | ||||||
|     Struct[0]; |     Struct[0]; | ||||||
|  // ^^^^^^ adjustments: Borrow(Ref('?2, Not))
 |  // ^^^^^^ adjustments: Borrow(Ref('?0, Not))
 | ||||||
|     StructMut[0]; |     StructMut[0]; | ||||||
|  // ^^^^^^^^^ adjustments: Borrow(Ref('?5, Not))
 |  // ^^^^^^^^^ adjustments: Borrow(Ref('?1, Not))
 | ||||||
|     &mut StructMut[0]; |     &mut StructMut[0]; | ||||||
|       // ^^^^^^^^^ adjustments: Borrow(Ref('?8, Mut))
 |       // ^^^^^^^^^ adjustments: Borrow(Ref('?2, Mut))
 | ||||||
| }",
 | }",
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -589,6 +589,7 @@ fn main() { | ||||||
|                 "attrs_shim", |                 "attrs_shim", | ||||||
|                 "attrs_shim", |                 "attrs_shim", | ||||||
|                 "return_type_impl_traits_shim", |                 "return_type_impl_traits_shim", | ||||||
|  |                 "generic_predicates_ns_shim", | ||||||
|                 "infer_shim", |                 "infer_shim", | ||||||
|                 "function_signature_shim", |                 "function_signature_shim", | ||||||
|                 "function_signature_with_source_map_shim", |                 "function_signature_with_source_map_shim", | ||||||
|  | @ -605,8 +606,6 @@ fn main() { | ||||||
|                 "impl_signature_shim", |                 "impl_signature_shim", | ||||||
|                 "impl_signature_with_source_map_shim", |                 "impl_signature_with_source_map_shim", | ||||||
|                 "callable_item_signature_shim", |                 "callable_item_signature_shim", | ||||||
|                 "adt_variance_shim", |  | ||||||
|                 "variances_of_shim", |  | ||||||
|                 "trait_impls_in_deps_shim", |                 "trait_impls_in_deps_shim", | ||||||
|                 "trait_impls_in_crate_shim", |                 "trait_impls_in_crate_shim", | ||||||
|                 "impl_trait_with_diagnostics_shim", |                 "impl_trait_with_diagnostics_shim", | ||||||
|  | @ -615,7 +614,6 @@ fn main() { | ||||||
|                 "impl_trait_with_diagnostics_ns_shim", |                 "impl_trait_with_diagnostics_ns_shim", | ||||||
|                 "impl_self_ty_with_diagnostics_ns_shim", |                 "impl_self_ty_with_diagnostics_ns_shim", | ||||||
|                 "generic_predicates_ns_shim", |                 "generic_predicates_ns_shim", | ||||||
|                 "generic_predicates_ns_shim", |  | ||||||
|                 "value_ty_shim", |                 "value_ty_shim", | ||||||
|                 "generic_predicates_shim", |                 "generic_predicates_shim", | ||||||
|                 "lang_item", |                 "lang_item", | ||||||
|  | @ -691,6 +689,7 @@ fn main() { | ||||||
|                 "attrs_shim", |                 "attrs_shim", | ||||||
|                 "attrs_shim", |                 "attrs_shim", | ||||||
|                 "return_type_impl_traits_shim", |                 "return_type_impl_traits_shim", | ||||||
|  |                 "generic_predicates_ns_shim", | ||||||
|                 "infer_shim", |                 "infer_shim", | ||||||
|                 "function_signature_with_source_map_shim", |                 "function_signature_with_source_map_shim", | ||||||
|                 "expr_scopes_shim", |                 "expr_scopes_shim", | ||||||
|  | @ -706,7 +705,6 @@ fn main() { | ||||||
|                 "impl_trait_with_diagnostics_ns_shim", |                 "impl_trait_with_diagnostics_ns_shim", | ||||||
|                 "impl_self_ty_with_diagnostics_ns_shim", |                 "impl_self_ty_with_diagnostics_ns_shim", | ||||||
|                 "generic_predicates_ns_shim", |                 "generic_predicates_ns_shim", | ||||||
|                 "generic_predicates_ns_shim", |  | ||||||
|                 "generic_predicates_shim", |                 "generic_predicates_shim", | ||||||
|             ] |             ] | ||||||
|         "#]],
 |         "#]],
 | ||||||
|  |  | ||||||
|  | @ -202,7 +202,7 @@ fn expr_macro_def_expanded_in_various_places() { | ||||||
|             100..119 'for _ ...!() {}': {unknown} |             100..119 'for _ ...!() {}': {unknown} | ||||||
|             100..119 'for _ ...!() {}': &'? mut {unknown} |             100..119 'for _ ...!() {}': &'? mut {unknown} | ||||||
|             100..119 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |             100..119 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | ||||||
|             100..119 'for _ ...!() {}': Option<{unknown}> |             100..119 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item> | ||||||
|             100..119 'for _ ...!() {}': () |             100..119 'for _ ...!() {}': () | ||||||
|             100..119 'for _ ...!() {}': () |             100..119 'for _ ...!() {}': () | ||||||
|             100..119 'for _ ...!() {}': () |             100..119 'for _ ...!() {}': () | ||||||
|  | @ -296,7 +296,7 @@ fn expr_macro_rules_expanded_in_various_places() { | ||||||
|             114..133 'for _ ...!() {}': {unknown} |             114..133 'for _ ...!() {}': {unknown} | ||||||
|             114..133 'for _ ...!() {}': &'? mut {unknown} |             114..133 'for _ ...!() {}': &'? mut {unknown} | ||||||
|             114..133 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |             114..133 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | ||||||
|             114..133 'for _ ...!() {}': Option<{unknown}> |             114..133 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item> | ||||||
|             114..133 'for _ ...!() {}': () |             114..133 'for _ ...!() {}': () | ||||||
|             114..133 'for _ ...!() {}': () |             114..133 'for _ ...!() {}': () | ||||||
|             114..133 'for _ ...!() {}': () |             114..133 'for _ ...!() {}': () | ||||||
|  |  | ||||||
|  | @ -1876,9 +1876,9 @@ impl Foo { | ||||||
| } | } | ||||||
| fn test() { | fn test() { | ||||||
|     Foo.foo(); |     Foo.foo(); | ||||||
|   //^^^ adjustments: Borrow(Ref('?1, Not))
 |   //^^^ adjustments: Borrow(Ref('?0, Not))
 | ||||||
|     (&Foo).foo(); |     (&Foo).foo(); | ||||||
|   // ^^^^ adjustments: Deref(None), Borrow(Ref('?3, Not))
 |   // ^^^^ adjustments: Deref(None), Borrow(Ref('?2, Not))
 | ||||||
| } | } | ||||||
| "#,
 | "#,
 | ||||||
|     ); |     ); | ||||||
|  | @ -1892,7 +1892,7 @@ fn receiver_adjustment_unsize_array() { | ||||||
| fn test() { | fn test() { | ||||||
|     let a = [1, 2, 3]; |     let a = [1, 2, 3]; | ||||||
|     a.len(); |     a.len(); | ||||||
| } //^ adjustments: Borrow(Ref('?7, Not)), Pointer(Unsize)
 | } //^ adjustments: Borrow(Ref('?0, Not)), Pointer(Unsize)
 | ||||||
| "#,
 | "#,
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  | @ -2105,7 +2105,7 @@ impl Foo { | ||||||
| } | } | ||||||
| fn test() { | fn test() { | ||||||
|     Box::new(Foo).foo(); |     Box::new(Foo).foo(); | ||||||
|   //^^^^^^^^^^^^^ adjustments: Deref(None), Borrow(Ref('?5, Not))
 |   //^^^^^^^^^^^^^ adjustments: Deref(None), Borrow(Ref('?0, Not))
 | ||||||
| } | } | ||||||
| "#,
 | "#,
 | ||||||
|     ); |     ); | ||||||
|  | @ -2123,7 +2123,7 @@ impl Foo { | ||||||
| use core::mem::ManuallyDrop; | use core::mem::ManuallyDrop; | ||||||
| fn test() { | fn test() { | ||||||
|     ManuallyDrop::new(Foo).foo(); |     ManuallyDrop::new(Foo).foo(); | ||||||
|   //^^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('?6, Not))
 |   //^^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('?0, Not))
 | ||||||
| } | } | ||||||
| "#,
 | "#,
 | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  | @ -362,12 +362,12 @@ fn diverging_expression_3_break() { | ||||||
|             140..141 'x': u32 |             140..141 'x': u32 | ||||||
|             149..175 '{ for ...; }; }': u32 |             149..175 '{ for ...; }; }': u32 | ||||||
|             151..172 'for a ...eak; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter |             151..172 'for a ...eak; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter | ||||||
|             151..172 'for a ...eak; }': {unknown} |             151..172 'for a ...eak; }': <{unknown} as IntoIterator>::IntoIter | ||||||
|             151..172 'for a ...eak; }': ! |             151..172 'for a ...eak; }': ! | ||||||
|             151..172 'for a ...eak; }': {unknown} |             151..172 'for a ...eak; }': <{unknown} as IntoIterator>::IntoIter | ||||||
|             151..172 'for a ...eak; }': &'? mut {unknown} |             151..172 'for a ...eak; }': &'? mut <{unknown} as IntoIterator>::IntoIter | ||||||
|             151..172 'for a ...eak; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |             151..172 'for a ...eak; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | ||||||
|             151..172 'for a ...eak; }': Option<{unknown}> |             151..172 'for a ...eak; }': Option<<{unknown} as Iterator>::Item> | ||||||
|             151..172 'for a ...eak; }': () |             151..172 'for a ...eak; }': () | ||||||
|             151..172 'for a ...eak; }': () |             151..172 'for a ...eak; }': () | ||||||
|             151..172 'for a ...eak; }': () |             151..172 'for a ...eak; }': () | ||||||
|  | @ -379,12 +379,12 @@ fn diverging_expression_3_break() { | ||||||
|             226..227 'x': u32 |             226..227 'x': u32 | ||||||
|             235..253 '{ for ... {}; }': u32 |             235..253 '{ for ... {}; }': u32 | ||||||
|             237..250 'for a in b {}': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter |             237..250 'for a in b {}': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter | ||||||
|             237..250 'for a in b {}': {unknown} |             237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter | ||||||
|             237..250 'for a in b {}': ! |             237..250 'for a in b {}': ! | ||||||
|             237..250 'for a in b {}': {unknown} |             237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter | ||||||
|             237..250 'for a in b {}': &'? mut {unknown} |             237..250 'for a in b {}': &'? mut <{unknown} as IntoIterator>::IntoIter | ||||||
|             237..250 'for a in b {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |             237..250 'for a in b {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | ||||||
|             237..250 'for a in b {}': Option<{unknown}> |             237..250 'for a in b {}': Option<<{unknown} as Iterator>::Item> | ||||||
|             237..250 'for a in b {}': () |             237..250 'for a in b {}': () | ||||||
|             237..250 'for a in b {}': () |             237..250 'for a in b {}': () | ||||||
|             237..250 'for a in b {}': () |             237..250 'for a in b {}': () | ||||||
|  | @ -395,12 +395,12 @@ fn diverging_expression_3_break() { | ||||||
|             304..305 'x': u32 |             304..305 'x': u32 | ||||||
|             313..340 '{ for ...; }; }': u32 |             313..340 '{ for ...; }; }': u32 | ||||||
|             315..337 'for a ...urn; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter |             315..337 'for a ...urn; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter | ||||||
|             315..337 'for a ...urn; }': {unknown} |             315..337 'for a ...urn; }': <{unknown} as IntoIterator>::IntoIter | ||||||
|             315..337 'for a ...urn; }': ! |             315..337 'for a ...urn; }': ! | ||||||
|             315..337 'for a ...urn; }': {unknown} |             315..337 'for a ...urn; }': <{unknown} as IntoIterator>::IntoIter | ||||||
|             315..337 'for a ...urn; }': &'? mut {unknown} |             315..337 'for a ...urn; }': &'? mut <{unknown} as IntoIterator>::IntoIter | ||||||
|             315..337 'for a ...urn; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |             315..337 'for a ...urn; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | ||||||
|             315..337 'for a ...urn; }': Option<{unknown}> |             315..337 'for a ...urn; }': Option<<{unknown} as Iterator>::Item> | ||||||
|             315..337 'for a ...urn; }': () |             315..337 'for a ...urn; }': () | ||||||
|             315..337 'for a ...urn; }': () |             315..337 'for a ...urn; }': () | ||||||
|             315..337 'for a ...urn; }': () |             315..337 'for a ...urn; }': () | ||||||
|  |  | ||||||
|  | @ -134,6 +134,9 @@ static ALIAS: AliasTy = { | ||||||
| "#,
 | "#,
 | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  |     // FIXME(next-solver): This should emit type mismatch error but leaving it for now
 | ||||||
|  |     // as we should fully migrate into next-solver without chalk-ir and TAIT should be
 | ||||||
|  |     // reworked on r-a to handle `#[define_opaque(T)]`
 | ||||||
|     check_infer_with_mismatches( |     check_infer_with_mismatches( | ||||||
|         r#" |         r#" | ||||||
| trait Trait {} | trait Trait {} | ||||||
|  | @ -155,7 +158,6 @@ static ALIAS: i32 = { | ||||||
|             191..193 '_a': impl Trait + ?Sized |             191..193 '_a': impl Trait + ?Sized | ||||||
|             205..211 'Struct': Struct |             205..211 'Struct': Struct | ||||||
|             217..218 '5': i32 |             217..218 '5': i32 | ||||||
|             205..211: expected impl Trait + ?Sized, got Struct |  | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -48,12 +48,12 @@ fn infer_pattern() { | ||||||
|             83..84 '1': i32 |             83..84 '1': i32 | ||||||
|             86..93 '"hello"': &'static str |             86..93 '"hello"': &'static str | ||||||
|             101..151 'for (e...     }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter |             101..151 'for (e...     }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter | ||||||
|             101..151 'for (e...     }': {unknown} |             101..151 'for (e...     }': <{unknown} as IntoIterator>::IntoIter | ||||||
|             101..151 'for (e...     }': ! |             101..151 'for (e...     }': ! | ||||||
|             101..151 'for (e...     }': {unknown} |             101..151 'for (e...     }': <{unknown} as IntoIterator>::IntoIter | ||||||
|             101..151 'for (e...     }': &'? mut {unknown} |             101..151 'for (e...     }': &'? mut <{unknown} as IntoIterator>::IntoIter | ||||||
|             101..151 'for (e...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |             101..151 'for (e...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | ||||||
|             101..151 'for (e...     }': Option<({unknown}, {unknown})> |             101..151 'for (e...     }': Option<<{unknown} as Iterator>::Item> | ||||||
|             101..151 'for (e...     }': () |             101..151 'for (e...     }': () | ||||||
|             101..151 'for (e...     }': () |             101..151 'for (e...     }': () | ||||||
|             101..151 'for (e...     }': () |             101..151 'for (e...     }': () | ||||||
|  | @ -719,28 +719,28 @@ fn test() { | ||||||
|             51..58 'loop {}': ! |             51..58 'loop {}': ! | ||||||
|             56..58 '{}': () |             56..58 '{}': () | ||||||
|             72..171 '{     ... x); }': () |             72..171 '{     ... x); }': () | ||||||
|             78..81 'foo': fn foo<&'? (i32, &'? str), i32, impl FnOnce(&'? (i32, &'? str)) -> i32>(&'? (i32, &'? str), impl FnOnce(&'? (i32, &'? str)) -> i32) -> i32 |             78..81 'foo': fn foo<&'? (i32, &'static str), i32, impl FnOnce(&'? (i32, &'static str)) -> i32>(&'? (i32, &'static str), impl FnOnce(&'? (i32, &'static str)) -> i32) -> i32 | ||||||
|             78..105 'foo(&(...y)| x)': i32 |             78..105 'foo(&(...y)| x)': i32 | ||||||
|             82..91 '&(1, "a")': &'? (i32, &'static str) |             82..91 '&(1, "a")': &'? (i32, &'static str) | ||||||
|             83..91 '(1, "a")': (i32, &'static str) |             83..91 '(1, "a")': (i32, &'static str) | ||||||
|             84..85 '1': i32 |             84..85 '1': i32 | ||||||
|             87..90 '"a"': &'static str |             87..90 '"a"': &'static str | ||||||
|             93..104 '|&(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> i32 |             93..104 '|&(x, y)| x': impl FnOnce(&'? (i32, &'static str)) -> i32 | ||||||
|             94..101 '&(x, y)': &'? (i32, &'? str) |             94..101 '&(x, y)': &'? (i32, &'static str) | ||||||
|             95..101 '(x, y)': (i32, &'? str) |             95..101 '(x, y)': (i32, &'static str) | ||||||
|             96..97 'x': i32 |             96..97 'x': i32 | ||||||
|             99..100 'y': &'? str |             99..100 'y': &'static str | ||||||
|             103..104 'x': i32 |             103..104 'x': i32 | ||||||
|             142..145 'foo': fn foo<&'? (i32, &'? str), &'? i32, impl FnOnce(&'? (i32, &'? str)) -> &'? i32>(&'? (i32, &'? str), impl FnOnce(&'? (i32, &'? str)) -> &'? i32) -> &'? i32 |             142..145 'foo': fn foo<&'? (i32, &'static str), &'? i32, impl FnOnce(&'? (i32, &'static str)) -> &'? i32>(&'? (i32, &'static str), impl FnOnce(&'? (i32, &'static str)) -> &'? i32) -> &'? i32 | ||||||
|             142..168 'foo(&(...y)| x)': &'? i32 |             142..168 'foo(&(...y)| x)': &'? i32 | ||||||
|             146..155 '&(1, "a")': &'? (i32, &'static str) |             146..155 '&(1, "a")': &'? (i32, &'static str) | ||||||
|             147..155 '(1, "a")': (i32, &'static str) |             147..155 '(1, "a")': (i32, &'static str) | ||||||
|             148..149 '1': i32 |             148..149 '1': i32 | ||||||
|             151..154 '"a"': &'static str |             151..154 '"a"': &'static str | ||||||
|             157..167 '|(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> &'? i32 |             157..167 '|(x, y)| x': impl FnOnce(&'? (i32, &'static str)) -> &'? i32 | ||||||
|             158..164 '(x, y)': (i32, &'? str) |             158..164 '(x, y)': (i32, &'static str) | ||||||
|             159..160 'x': &'? i32 |             159..160 'x': &'? i32 | ||||||
|             162..163 'y': &'? &'? str |             162..163 'y': &'? &'static str | ||||||
|             166..167 'x': &'? i32 |             166..167 'x': &'? i32 | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  | @ -268,12 +268,12 @@ fn infer_std_crash_5() { | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             26..322 '{     ...   } }': () |             26..322 '{     ...   } }': () | ||||||
|             32..320 'for co...     }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter |             32..320 'for co...     }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter | ||||||
|             32..320 'for co...     }': {unknown} |             32..320 'for co...     }': <{unknown} as IntoIterator>::IntoIter | ||||||
|             32..320 'for co...     }': ! |             32..320 'for co...     }': ! | ||||||
|             32..320 'for co...     }': {unknown} |             32..320 'for co...     }': <{unknown} as IntoIterator>::IntoIter | ||||||
|             32..320 'for co...     }': &'? mut {unknown} |             32..320 'for co...     }': &'? mut <{unknown} as IntoIterator>::IntoIter | ||||||
|             32..320 'for co...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |             32..320 'for co...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | ||||||
|             32..320 'for co...     }': Option<{unknown}> |             32..320 'for co...     }': Option<<{unknown} as Iterator>::Item> | ||||||
|             32..320 'for co...     }': () |             32..320 'for co...     }': () | ||||||
|             32..320 'for co...     }': () |             32..320 'for co...     }': () | ||||||
|             32..320 'for co...     }': () |             32..320 'for co...     }': () | ||||||
|  | @ -628,7 +628,7 @@ fn issue_4053_diesel_where_clauses() { | ||||||
|             65..69 'self': Self |             65..69 'self': Self | ||||||
|             267..271 'self': Self |             267..271 'self': Self | ||||||
|             466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> |             466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | ||||||
|             488..522 '{     ...     }': () |             488..522 '{     ...     }': <SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> as BoxedDsl<DB>>::Output | ||||||
|             498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> |             498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | ||||||
|             498..508 'self.order': O |             498..508 'self.order': O | ||||||
|             498..515 'self.o...into()': dyn QueryFragment<DB> + '? |             498..515 'self.o...into()': dyn QueryFragment<DB> + '? | ||||||
|  | @ -1248,7 +1248,7 @@ fn test() { | ||||||
|             16..66 'for _ ...     }': {unknown} |             16..66 'for _ ...     }': {unknown} | ||||||
|             16..66 'for _ ...     }': &'? mut {unknown} |             16..66 'for _ ...     }': &'? mut {unknown} | ||||||
|             16..66 'for _ ...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |             16..66 'for _ ...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> | ||||||
|             16..66 'for _ ...     }': Option<{unknown}> |             16..66 'for _ ...     }': Option<<{unknown} as Iterator>::Item> | ||||||
|             16..66 'for _ ...     }': () |             16..66 'for _ ...     }': () | ||||||
|             16..66 'for _ ...     }': () |             16..66 'for _ ...     }': () | ||||||
|             16..66 'for _ ...     }': () |             16..66 'for _ ...     }': () | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ impl<'a> IntoIterator for &'a Grid { | ||||||
|     "#,
 |     "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             150..154 'self': &'a Grid |             150..154 'self': &'a Grid | ||||||
|             174..181 '{     }': impl Iterator<Item = &'a ()> |             174..181 '{     }': impl Iterator<Item = &'? ()> | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1954,6 +1954,8 @@ fn closure_return_inferred() { | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // FIXME(next-solver): `&'? str` in 231..262 seems suspicious.
 | ||||||
|  | // Should revisit this once we fully migrated into next-solver without chalk-ir.
 | ||||||
| #[test] | #[test] | ||||||
| fn coroutine_types_inferred() { | fn coroutine_types_inferred() { | ||||||
|     check_infer( |     check_infer( | ||||||
|  | @ -1998,7 +2000,7 @@ fn test() { | ||||||
|             225..360 'match ...     }': () |             225..360 'match ...     }': () | ||||||
|             231..239 'Pin::new': fn new<&'? mut |usize| yields i64 -> &'static str>(&'? mut |usize| yields i64 -> &'static str) -> Pin<&'? mut |usize| yields i64 -> &'static str> |             231..239 'Pin::new': fn new<&'? mut |usize| yields i64 -> &'static str>(&'? mut |usize| yields i64 -> &'static str) -> Pin<&'? mut |usize| yields i64 -> &'static str> | ||||||
|             231..247 'Pin::n...mut g)': Pin<&'? mut |usize| yields i64 -> &'static str> |             231..247 'Pin::n...mut g)': Pin<&'? mut |usize| yields i64 -> &'static str> | ||||||
|             231..262 'Pin::n...usize)': CoroutineState<i64, &'static str> |             231..262 'Pin::n...usize)': CoroutineState<i64, &'? str> | ||||||
|             240..246 '&mut g': &'? mut |usize| yields i64 -> &'static str |             240..246 '&mut g': &'? mut |usize| yields i64 -> &'static str | ||||||
|             245..246 'g': |usize| yields i64 -> &'static str |             245..246 'g': |usize| yields i64 -> &'static str | ||||||
|             255..261 '0usize': usize |             255..261 '0usize': usize | ||||||
|  |  | ||||||
|  | @ -1,6 +1,8 @@ | ||||||
| use cov_mark::check; | use cov_mark::check; | ||||||
| use expect_test::expect; | use expect_test::expect; | ||||||
| 
 | 
 | ||||||
|  | use crate::tests::infer_with_mismatches; | ||||||
|  | 
 | ||||||
| use super::{check, check_infer, check_infer_with_mismatches, check_no_mismatches, check_types}; | use super::{check, check_infer, check_infer_with_mismatches, check_no_mismatches, check_types}; | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
|  | @ -2460,7 +2462,7 @@ use core::ops::Index; | ||||||
| 
 | 
 | ||||||
| type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||||||
| 
 | 
 | ||||||
| pub trait UnificationStoreBase: Index<Output = Key<Self>> { | pub trait UnificationStoreBase: Index<usize, Output = Key<Self>> { | ||||||
|     type Key; |     type Key; | ||||||
| 
 | 
 | ||||||
|     fn len(&self) -> usize; |     fn len(&self) -> usize; | ||||||
|  | @ -3634,8 +3636,7 @@ fn minimized() { | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn no_builtin_binop_expectation_for_general_ty_var() { | fn no_builtin_binop_expectation_for_general_ty_var() { | ||||||
|     // FIXME: Ideally type mismatch should be reported on `take_u32(42 - p)`.
 |     infer_with_mismatches( | ||||||
|     check_types( |  | ||||||
|         r#" |         r#" | ||||||
| //- minicore: add
 | //- minicore: add
 | ||||||
| use core::ops::Add; | use core::ops::Add; | ||||||
|  | @ -3659,6 +3660,7 @@ fn minimized() { | ||||||
|     take_u32(42 + p); |     take_u32(42 + p); | ||||||
| } | } | ||||||
| "#,
 | "#,
 | ||||||
|  |         true, | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -4188,6 +4190,8 @@ fn g<P: PointerFamily>(p: <P as PointerFamily>::Pointer<i32>) { | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // FIXME(next-solver): Was `&'a T` but now getting error lifetime.
 | ||||||
|  | // This might be fixed once we migrate into next-solver fully without chalk-ir in lowering.
 | ||||||
| #[test] | #[test] | ||||||
| fn gats_with_impl_trait() { | fn gats_with_impl_trait() { | ||||||
|     // FIXME: the last function (`fn i()`) is not valid Rust as of this writing because you cannot
 |     // FIXME: the last function (`fn i()`) is not valid Rust as of this writing because you cannot
 | ||||||
|  | @ -4211,21 +4215,21 @@ fn f<T>(v: impl Trait) { | ||||||
| } | } | ||||||
| fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) { | fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) { | ||||||
|     let a = v.get::<T>(); |     let a = v.get::<T>(); | ||||||
|       //^ &'a T
 |       //^ &'? T
 | ||||||
|     let a = v.get::<()>(); |     let a = v.get::<()>(); | ||||||
|       //^ <impl Trait<Assoc<T> = &'a T> as Trait>::Assoc<()>
 |       //^ <impl Trait<Assoc<T> = &'a T> as Trait>::Assoc<()>
 | ||||||
| } | } | ||||||
| fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) { | fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) { | ||||||
|     let a = v.get::<i32>(); |     let a = v.get::<i32>(); | ||||||
|       //^ &'a i32
 |       //^ &'? i32
 | ||||||
|     let a = v.get::<i64>(); |     let a = v.get::<i64>(); | ||||||
|       //^ &'a i64
 |       //^ &'? i64
 | ||||||
| } | } | ||||||
| fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) { | fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) { | ||||||
|     let a = v.get::<i32>(); |     let a = v.get::<i32>(); | ||||||
|       //^ &'a i32
 |       //^ &'? i32
 | ||||||
|     let a = v.get::<i64>(); |     let a = v.get::<i64>(); | ||||||
|       //^ &'a i64
 |       //^ &'? i64
 | ||||||
| } | } | ||||||
|     "#,
 |     "#,
 | ||||||
|     ); |     ); | ||||||
|  | @ -4255,8 +4259,8 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) { | ||||||
|             127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?) |             127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?) | ||||||
|             164..195 '{     ...f(); }': () |             164..195 '{     ...f(); }': () | ||||||
|             170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?) |             170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?) | ||||||
|             170..184 'v.get::<i32>()': {unknown} |             170..184 'v.get::<i32>()': <dyn Trait<Assoc<i32> = &'a i32> + '? as Trait>::Assoc<i32> | ||||||
|             170..192 'v.get:...eref()': &'? {unknown} |             170..192 'v.get:...eref()': {unknown} | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  | @ -4931,6 +4935,8 @@ fn main() { | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // FIXME(next-solver): Was `<D as Deserializer<'de>>::Error` but now getting error lifetime.
 | ||||||
|  | // This might be fixed once we migrate into next-solver fully without chalk-ir in lowering.
 | ||||||
| #[test] | #[test] | ||||||
| fn new_solver_crash_1() { | fn new_solver_crash_1() { | ||||||
|     check_infer( |     check_infer( | ||||||
|  | @ -4947,7 +4953,7 @@ where | ||||||
| "#,
 | "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             84..86 'de': D |             84..86 'de': D | ||||||
|             135..138 '{ }': <D as Deserializer<'de>>::Error |             135..138 '{ }': <D as Deserializer<'?>>::Error | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -21,9 +21,17 @@ use stdx::never; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     db::HirDatabase, infer::unify::InferenceTable, next_solver::{ |     AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTy, | ||||||
|         infer::{DbInternerInferExt, InferCtxt}, mapping::{convert_canonical_args_for_result, ChalkToNextSolver}, util::mini_canonicalize, DbInterner, GenericArg, Predicate, SolverContext, Span |     ProjectionTyExt, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause, | ||||||
|     }, utils::UnevaluatedConstEvaluatorFolder, AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTy, ProjectionTyExt, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause |     db::HirDatabase, | ||||||
|  |     infer::unify::InferenceTable, | ||||||
|  |     next_solver::{ | ||||||
|  |         DbInterner, GenericArg, Predicate, SolverContext, Span, | ||||||
|  |         infer::{DbInternerInferExt, InferCtxt}, | ||||||
|  |         mapping::{ChalkToNextSolver, convert_canonical_args_for_result}, | ||||||
|  |         util::mini_canonicalize, | ||||||
|  |     }, | ||||||
|  |     utils::UnevaluatedConstEvaluatorFolder, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// A set of clauses that we assume to be true. E.g. if we are inside this function:
 | /// A set of clauses that we assume to be true. E.g. if we are inside this function:
 | ||||||
|  | @ -282,30 +290,18 @@ pub fn next_trait_solve( | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn next_trait_solve_canonical<'db>( | pub fn next_trait_solve_canonical_in_ctxt<'db>( | ||||||
|     db: &'db dyn HirDatabase, |     infer_ctxt: &InferCtxt<'db>, | ||||||
|     krate: Crate, |  | ||||||
|     block: Option<BlockId>, |  | ||||||
|     goal: crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, Predicate<'db>>>, |     goal: crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, Predicate<'db>>>, | ||||||
| ) -> NextTraitSolveResult { | ) -> NextTraitSolveResult { | ||||||
|     // FIXME: should use analysis_in_body, but that needs GenericDefId::Block
 |     let context = SolverContext(infer_ctxt.clone()); | ||||||
|     let context = SolverContext( |  | ||||||
|         DbInterner::new_with(db, Some(krate), block) |  | ||||||
|             .infer_ctxt() |  | ||||||
|             .build(TypingMode::non_body_analysis()), |  | ||||||
|     ); |  | ||||||
| 
 | 
 | ||||||
|     tracing::info!(?goal); |     tracing::info!(?goal); | ||||||
| 
 | 
 | ||||||
|     let (goal, var_values) = |     let (goal, var_values) = context.instantiate_canonical(&goal); | ||||||
|         context.instantiate_canonical(&goal); |  | ||||||
|     tracing::info!(?var_values); |     tracing::info!(?var_values); | ||||||
| 
 | 
 | ||||||
|     let res = context.evaluate_root_goal( |     let res = context.evaluate_root_goal(goal, Span::dummy(), None); | ||||||
|         goal.clone(), |  | ||||||
|         Span::dummy(), |  | ||||||
|         None |  | ||||||
|     ); |  | ||||||
| 
 | 
 | ||||||
|     let vars = |     let vars = | ||||||
|         var_values.var_values.iter().map(|g| context.0.resolve_vars_if_possible(g)).collect(); |         var_values.var_values.iter().map(|g| context.0.resolve_vars_if_possible(g)).collect(); | ||||||
|  | @ -318,13 +314,10 @@ pub fn next_trait_solve_canonical<'db>( | ||||||
|     match res { |     match res { | ||||||
|         Err(_) => NextTraitSolveResult::NoSolution, |         Err(_) => NextTraitSolveResult::NoSolution, | ||||||
|         Ok((_, Certainty::Yes, args)) => NextTraitSolveResult::Certain( |         Ok((_, Certainty::Yes, args)) => NextTraitSolveResult::Certain( | ||||||
|             convert_canonical_args_for_result(DbInterner::new_with(db, Some(krate), block), args) |             convert_canonical_args_for_result(infer_ctxt.interner, args), | ||||||
|         ), |         ), | ||||||
|         Ok((_, Certainty::Maybe(_), args)) => { |         Ok((_, Certainty::Maybe(_), args)) => { | ||||||
|             let subst = convert_canonical_args_for_result( |             let subst = convert_canonical_args_for_result(infer_ctxt.interner, args); | ||||||
|                 DbInterner::new_with(db, Some(krate), block), |  | ||||||
|                 args, |  | ||||||
|             ); |  | ||||||
|             NextTraitSolveResult::Uncertain(chalk_ir::Canonical { |             NextTraitSolveResult::Uncertain(chalk_ir::Canonical { | ||||||
|                 binders: subst.binders, |                 binders: subst.binders, | ||||||
|                 value: subst.value.subst, |                 value: subst.value.subst, | ||||||
|  |  | ||||||
|  | @ -14,7 +14,11 @@ use hir_expand::{ | ||||||
|     mod_path::{ModPath, PathKind}, |     mod_path::{ModPath, PathKind}, | ||||||
|     name::Name, |     name::Name, | ||||||
| }; | }; | ||||||
| use hir_ty::{db::HirDatabase, method_resolution, next_solver::{mapping::ChalkToNextSolver, DbInterner}}; | use hir_ty::{ | ||||||
|  |     db::HirDatabase, | ||||||
|  |     method_resolution, | ||||||
|  |     next_solver::{DbInterner, mapping::ChalkToNextSolver}, | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, |     Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, | ||||||
|  | @ -271,7 +275,11 @@ fn resolve_impl_trait_item<'db>( | ||||||
|     //
 |     //
 | ||||||
|     // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates)
 |     // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates)
 | ||||||
|     _ = method_resolution::iterate_path_candidates( |     _ = method_resolution::iterate_path_candidates( | ||||||
|         &canonical.to_nextsolver(DbInterner::new_with(db, Some(environment.krate), environment.block)), |         &canonical.to_nextsolver(DbInterner::new_with( | ||||||
|  |             db, | ||||||
|  |             Some(environment.krate), | ||||||
|  |             environment.block, | ||||||
|  |         )), | ||||||
|         db, |         db, | ||||||
|         environment, |         environment, | ||||||
|         &traits_in_scope, |         &traits_in_scope, | ||||||
|  |  | ||||||
|  | @ -10,7 +10,8 @@ use crate::{ | ||||||
| fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { | fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { | ||||||
|     let (db, pos) = position(ra_fixture); |     let (db, pos) = position(ra_fixture); | ||||||
|     let config = TEST_CONFIG; |     let config = TEST_CONFIG; | ||||||
|     let (completion_context, _analysis) = CompletionContext::new(&db, pos, &config).unwrap(); |     let (completion_context, _analysis) = | ||||||
|  |         salsa::attach(&db, || CompletionContext::new(&db, pos, &config).unwrap()); | ||||||
| 
 | 
 | ||||||
|     let ty = completion_context |     let ty = completion_context | ||||||
|         .expected_type |         .expected_type | ||||||
|  |  | ||||||
|  | @ -526,8 +526,7 @@ fn main() { | ||||||
|             fn run(_t: Rate<5>) { |             fn run(_t: Rate<5>) { | ||||||
|             } |             } | ||||||
|             fn main() { |             fn main() { | ||||||
|                 run(f()) // FIXME: remove this error
 |                 run(f()) | ||||||
|                   //^^^ error: expected Rate<5>, found Rate<_>
 |  | ||||||
|             } |             } | ||||||
| "#,
 | "#,
 | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|  | @ -2,7 +2,10 @@ use expect_test::{Expect, expect}; | ||||||
| use hir::{FilePosition, FileRange}; | use hir::{FilePosition, FileRange}; | ||||||
| use ide_db::{ | use ide_db::{ | ||||||
|     EditionedFileId, FxHashSet, |     EditionedFileId, FxHashSet, | ||||||
|     base_db::{SourceDatabase, salsa::Durability}, |     base_db::{ | ||||||
|  |         SourceDatabase, | ||||||
|  |         salsa::{self, Durability}, | ||||||
|  |     }, | ||||||
| }; | }; | ||||||
| use test_utils::RangeOrOffset; | use test_utils::RangeOrOffset; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
|  | @ -116,7 +119,7 @@ fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) { | ||||||
|         let rule: SsrRule = rule.parse().unwrap(); |         let rule: SsrRule = rule.parse().unwrap(); | ||||||
|         match_finder.add_rule(rule).unwrap(); |         match_finder.add_rule(rule).unwrap(); | ||||||
|     } |     } | ||||||
|     let edits = match_finder.edits(); |     let edits = salsa::attach(&db, || match_finder.edits()); | ||||||
|     if edits.is_empty() { |     if edits.is_empty() { | ||||||
|         panic!("No edits were made"); |         panic!("No edits were made"); | ||||||
|     } |     } | ||||||
|  | @ -155,8 +158,12 @@ fn assert_matches(pattern: &str, code: &str, expected: &[&str]) { | ||||||
|     ) |     ) | ||||||
|     .unwrap(); |     .unwrap(); | ||||||
|     match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); |     match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); | ||||||
|     let matched_strings: Vec<String> = |     let matched_strings: Vec<String> = salsa::attach(&db, || match_finder.matches()) | ||||||
|         match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect(); |         .flattened() | ||||||
|  |         .matches | ||||||
|  |         .iter() | ||||||
|  |         .map(|m| m.matched_text()) | ||||||
|  |         .collect(); | ||||||
|     if matched_strings != expected && !expected.is_empty() { |     if matched_strings != expected && !expected.is_empty() { | ||||||
|         print_match_debug_info(&match_finder, position.file_id, expected[0]); |         print_match_debug_info(&match_finder, position.file_id, expected[0]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -47,7 +47,8 @@ fn check_rewrite(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect | ||||||
|     let (analysis, position) = fixture::position(ra_fixture); |     let (analysis, position) = fixture::position(ra_fixture); | ||||||
|     let sema = &Semantics::new(&analysis.db); |     let sema = &Semantics::new(&analysis.db); | ||||||
|     let (cursor_def, docs, range) = def_under_cursor(sema, &position); |     let (cursor_def, docs, range) = def_under_cursor(sema, &position); | ||||||
|     let res = rewrite_links(sema.db, docs.as_str(), cursor_def, Some(range)); |     let res = | ||||||
|  |         salsa::attach(sema.db, || rewrite_links(sema.db, docs.as_str(), cursor_def, Some(range))); | ||||||
|     expect.assert_eq(&res) |     expect.assert_eq(&res) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Shoyu Vanilla
						Shoyu Vanilla