Auto merge of #17268 - Veykril:signatures, r=Veykril · rust-lang/rust@24bf53d
@@ -570,6 +570,10 @@ impl CallableSig {
570570}
571571}
572572573+pub fn abi(&self) -> FnAbi {
574+self.abi
575+}
576+573577pub fn params(&self) -> &[Ty] {
574578&self.params_and_return[0..self.params_and_return.len() - 1]
575579}
@@ -892,20 +896,16 @@ where
892896Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
893897}
894898895-pub fn callable_sig_from_fnonce(
896-mut self_ty: &Ty,
897-env: Arc<TraitEnvironment>,
899+pub fn callable_sig_from_fn_trait(
900+self_ty: &Ty,
901+trait_env: Arc<TraitEnvironment>,
898902db: &dyn HirDatabase,
899-) -> Option<CallableSig> {
900-if let Some((ty, _, _)) = self_ty.as_reference() {
901-// This will happen when it implements fn or fn mut, since we add a autoborrow adjustment
902- self_ty = ty;
903-}
904-let krate = env.krate;
903+) -> Option<(FnTrait, CallableSig)> {
904+let krate = trait_env.krate;
905905let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
906906let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
907907908-let mut table = InferenceTable::new(db, env);
908+let mut table = InferenceTable::new(db, trait_env.clone());
909909let b = TyBuilder::trait_ref(db, fn_once_trait);
910910if b.remaining() != 2 {
911911return None;
@@ -915,23 +915,56 @@ pub fn callable_sig_from_fnonce(
915915// - Self: FnOnce<?args_ty>
916916// - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
917917let args_ty = table.new_type_var();
918-let trait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
918+let mut trait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
919919let projection = TyBuilder::assoc_type_projection(
920920 db,
921921 output_assoc_type,
922922Some(trait_ref.substitution.clone()),
923923)
924924.build();
925- table.register_obligation(trait_ref.cast(Interner));
926-let ret_ty = table.normalize_projection_ty(projection);
927-928-let ret_ty = table.resolve_completely(ret_ty);
929-let args_ty = table.resolve_completely(args_ty);
930925931-let params =
932- args_ty.as_tuple()?.iter(Interner).map(|it| it.assert_ty_ref(Interner)).cloned().collect();
933-934-Some(CallableSig::from_params_and_return(params, ret_ty, false, Safety::Safe, FnAbi::RustCall))
926+let block = trait_env.block;
927+let trait_env = trait_env.env.clone();
928+let obligation =
929+InEnvironment { goal: trait_ref.clone().cast(Interner), environment: trait_env.clone() };
930+let canonical = table.canonicalize(obligation.clone());
931+if db.trait_solve(krate, block, canonical.cast(Interner)).is_some() {
932+ table.register_obligation(obligation.goal);
933+let return_ty = table.normalize_projection_ty(projection);
934+for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
935+let fn_x_trait = fn_x.get_id(db, krate)?;
936+ trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
937+let obligation: chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> = InEnvironment {
938+goal: trait_ref.clone().cast(Interner),
939+environment: trait_env.clone(),
940+};
941+let canonical = table.canonicalize(obligation.clone());
942+if db.trait_solve(krate, block, canonical.cast(Interner)).is_some() {
943+let ret_ty = table.resolve_completely(return_ty);
944+let args_ty = table.resolve_completely(args_ty);
945+let params = args_ty
946+.as_tuple()?
947+.iter(Interner)
948+.map(|it| it.assert_ty_ref(Interner))
949+.cloned()
950+.collect();
951+952+return Some((
953+ fn_x,
954+CallableSig::from_params_and_return(
955+ params,
956+ ret_ty,
957+false,
958+Safety::Safe,
959+FnAbi::RustCall,
960+),
961+));
962+}
963+}
964+unreachable!("It should at least implement FnOnce at this point");
965+} else {
966+None
967+}
935968}
936969937970struct PlaceholderCollector<'db> {