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+573577

pub fn params(&self) -> &[Ty] {

574578

&self.params_and_return[0..self.params_and_return.len() - 1]

575579

}

@@ -892,20 +896,16 @@ where

892896

Canonical { 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>,

898902

db: &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;

905905

let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;

906906

let 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());

909909

let b = TyBuilder::trait_ref(db, fn_once_trait);

910910

if b.remaining() != 2 {

911911

return 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

917917

let 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();

919919

let projection = TyBuilder::assoc_type_projection(

920920

db,

921921

output_assoc_type,

922922

Some(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

}

936969937970

struct PlaceholderCollector<'db> {