Skip to content

Commit 6a2127b

Browse files
committed
Cleanup checking for existing impls in impl From assist
Use the trait solver to check if there's an existing implementation of From<type_in_enum_variant> for the enum.
1 parent 1fee601 commit 6a2127b

File tree

2 files changed

+24
-48
lines changed

2 files changed

+24
-48
lines changed

crates/ra_assists/src/handlers/add_from_impl_for_enum.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use hir::ImplDef;
21
use ra_syntax::{
32
ast::{self, AstNode, NameOwner},
43
TextUnit,
@@ -99,18 +98,7 @@ fn already_has_from_impl(
9998
};
10099
let var_ty = hir_enum_var.fields(sema.db)[0].signature_ty(sema.db);
101100

102-
let krate = match scope.module() {
103-
Some(s) => s.krate(),
104-
_ => return false,
105-
};
106-
let impls = ImplDef::for_trait(sema.db, krate, from_trait);
107-
let imp = impls.iter().find(|imp| {
108-
let targets_enum = imp.target_ty(sema.db) == e_ty;
109-
let param_matches = imp.target_trait_substs_matches(sema.db, &[var_ty.clone()]);
110-
targets_enum && param_matches
111-
});
112-
113-
imp.is_some()
101+
e_ty.impls_trait(sema.db, from_trait, &[var_ty.clone()])
114102
}
115103

116104
#[cfg(test)]
@@ -192,7 +180,7 @@ impl From<String> for A {
192180
A::Two(v)
193181
}
194182
}
195-
183+
196184
pub trait From<T> {
197185
fn from(T) -> Self;
198186
}"#,
@@ -209,7 +197,7 @@ impl From<String> for A {
209197
A::Two(v)
210198
}
211199
}
212-
200+
213201
pub trait From<T> {
214202
fn from(T) -> Self;
215203
}"#,

crates/ra_hir/src/code_model.rs

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use hir_expand::{
2323
};
2424
use hir_ty::{
2525
autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy,
26-
Canonical, InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
26+
Canonical, InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor,
2727
};
2828
use ra_db::{CrateId, Edition, FileId};
2929
use ra_prof::profile;
@@ -960,38 +960,6 @@ impl ImplDef {
960960
db.impl_data(self.id).target_trait.clone()
961961
}
962962

963-
pub fn target_trait_substs_matches(&self, db: &dyn HirDatabase, typs: &[Type]) -> bool {
964-
let type_ref = match self.target_trait(db) {
965-
Some(typ_ref) => typ_ref,
966-
None => return false,
967-
};
968-
let resolver = self.id.resolver(db.upcast());
969-
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
970-
let ty = Ty::from_hir(&ctx, &type_ref);
971-
let d = match ty.dyn_trait_ref() {
972-
Some(d) => d,
973-
None => return false,
974-
};
975-
let mut matches = true;
976-
let mut i = 0;
977-
d.substs.walk(&mut |t| {
978-
if matches {
979-
if i >= typs.len() {
980-
matches = false;
981-
return;
982-
}
983-
match t {
984-
Ty::Bound(_) => matches = i == 0,
985-
_ => {
986-
matches = *t == typs[i].ty.value;
987-
i += 1;
988-
}
989-
}
990-
}
991-
});
992-
matches
993-
}
994-
995963
pub fn target_type(&self, db: &dyn HirDatabase) -> TypeRef {
996964
db.impl_data(self.id).target_type.clone()
997965
}
@@ -1116,6 +1084,26 @@ impl Type {
11161084
)
11171085
}
11181086

1087+
pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1088+
let trait_ref = hir_ty::TraitRef {
1089+
trait_: trait_.id,
1090+
substs: Substs::build_for_def(db, trait_.id)
1091+
.push(self.ty.value.clone())
1092+
.fill(args.iter().map(|t| t.ty.value.clone()))
1093+
.build(),
1094+
};
1095+
1096+
let goal = Canonical {
1097+
value: hir_ty::InEnvironment::new(
1098+
self.ty.environment.clone(),
1099+
hir_ty::Obligation::Trait(trait_ref),
1100+
),
1101+
num_vars: 0,
1102+
};
1103+
1104+
db.trait_solve(self.krate, goal).is_some()
1105+
}
1106+
11191107
// FIXME: this method is broken, as it doesn't take closures into account.
11201108
pub fn as_callable(&self) -> Option<CallableDef> {
11211109
Some(self.ty.value.as_callable()?.0)

0 commit comments

Comments
 (0)