Skip to content

Commit 0c35d82

Browse files
bors[bot]flodieboldbkchr
authored
Merge #1721 #1723
1721: Impl/dyn trait r=flodiebold a=flodiebold This adds support for `impl Trait` and `dyn Trait` types as far as possible without Chalk. So we can represent them in the type system, and handle them in method resolution, but Chalk doesn't know about them yet. There's a small temporary hack here where we bypass Chalk during method resolution, so we can handle simple method calls on them and completion works. Fixes #1608. 1723: Make sysroot use `RUST_SRC_PATH` if set r=matklad a=bkchr Co-authored-by: Florian Diebold <[email protected]> Co-authored-by: Bastian Köcher <[email protected]>
3 parents daf1a96 + 4768f5e + 18c7a1e commit 0c35d82

File tree

11 files changed

+471
-55
lines changed

11 files changed

+471
-55
lines changed

crates/ra_hir/src/generics.rs

+6-14
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
db::{AstDatabase, DefDatabase, HirDatabase},
1212
name::SELF_TYPE,
1313
path::Path,
14-
type_ref::TypeRef,
14+
type_ref::{TypeBound, TypeRef},
1515
AdtDef, AsName, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct,
1616
Trait, TypeAlias, Union,
1717
};
@@ -35,10 +35,12 @@ pub struct GenericParams {
3535

3636
/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined
3737
/// where clauses like `where T: Foo + Bar` are turned into multiple of these.
38+
/// It might still result in multiple actual predicates though, because of
39+
/// associated type bindings like `Iterator<Item = u32>`.
3840
#[derive(Clone, PartialEq, Eq, Debug)]
3941
pub struct WherePredicate {
4042
pub(crate) type_ref: TypeRef,
41-
pub(crate) trait_ref: Path,
43+
pub(crate) bound: TypeBound,
4244
}
4345

4446
// FIXME: consts can have type parameters from their parents (i.e. associated consts of traits)
@@ -143,18 +145,8 @@ impl GenericParams {
143145
// FIXME: remove this bound
144146
return;
145147
}
146-
let path = bound
147-
.type_ref()
148-
.and_then(|tr| match tr {
149-
ast::TypeRef::PathType(path) => path.path(),
150-
_ => None,
151-
})
152-
.and_then(Path::from_ast);
153-
let path = match path {
154-
Some(p) => p,
155-
None => return,
156-
};
157-
self.where_predicates.push(WherePredicate { type_ref, trait_ref: path });
148+
let bound = TypeBound::from_ast(bound);
149+
self.where_predicates.push(WherePredicate { type_ref, bound });
158150
}
159151

160152
pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {

crates/ra_hir/src/ty.rs

+123-10
Original file line numberDiff line numberDiff line change
@@ -161,14 +161,28 @@ pub enum Ty {
161161
name: Name,
162162
},
163163

164-
/// A bound type variable. Only used during trait resolution to represent
165-
/// Chalk variables.
164+
/// A bound type variable. Used during trait resolution to represent Chalk
165+
/// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type.
166166
Bound(u32),
167167

168168
/// A type variable used during type checking. Not to be confused with a
169169
/// type parameter.
170170
Infer(InferTy),
171171

172+
/// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
173+
///
174+
/// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)`
175+
/// represents the `Self` type inside the bounds. This is currently
176+
/// implicit; Chalk has the `Binders` struct to make it explicit, but it
177+
/// didn't seem worth the overhead yet.
178+
Dyn(Arc<[GenericPredicate]>),
179+
180+
/// An opaque type (`impl Trait`).
181+
///
182+
/// The predicates are quantified over the `Self` type; see `Ty::Dyn` for
183+
/// more.
184+
Opaque(Arc<[GenericPredicate]>),
185+
172186
/// A placeholder for a type which could not be computed; this is propagated
173187
/// to avoid useless error messages. Doubles as a placeholder where type
174188
/// variables are inserted before type checking, since we want to try to
@@ -194,6 +208,12 @@ impl Substs {
194208
Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into())
195209
}
196210

211+
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
212+
for t in self.0.iter() {
213+
t.walk(f);
214+
}
215+
}
216+
197217
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
198218
// Without an Arc::make_mut_slice, we can't avoid the clone here:
199219
let mut v: Vec<_> = self.0.iter().cloned().collect();
@@ -270,6 +290,14 @@ impl TraitRef {
270290
});
271291
self
272292
}
293+
294+
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
295+
self.substs.walk(f);
296+
}
297+
298+
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
299+
self.substs.walk_mut(f);
300+
}
273301
}
274302

275303
/// Like `generics::WherePredicate`, but with resolved types: A condition on the
@@ -299,6 +327,20 @@ impl GenericPredicate {
299327
GenericPredicate::Error => self,
300328
}
301329
}
330+
331+
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
332+
match self {
333+
GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f),
334+
GenericPredicate::Error => {}
335+
}
336+
}
337+
338+
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
339+
match self {
340+
GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f),
341+
GenericPredicate::Error => {}
342+
}
343+
}
302344
}
303345

304346
/// Basically a claim (currently not validated / checked) that the contained
@@ -386,6 +428,11 @@ impl Ty {
386428
t.walk(f);
387429
}
388430
}
431+
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
432+
for p in predicates.iter() {
433+
p.walk(f);
434+
}
435+
}
389436
Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
390437
}
391438
f(self);
@@ -402,6 +449,13 @@ impl Ty {
402449
Ty::UnselectedProjection(p_ty) => {
403450
p_ty.parameters.walk_mut(f);
404451
}
452+
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
453+
let mut v: Vec<_> = predicates.iter().cloned().collect();
454+
for p in &mut v {
455+
p.walk_mut(f);
456+
}
457+
*predicates = v.into();
458+
}
405459
Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
406460
}
407461
f(self);
@@ -529,6 +583,19 @@ impl Ty {
529583
ty => ty,
530584
})
531585
}
586+
587+
/// If this is an `impl Trait` or `dyn Trait`, returns that trait.
588+
pub fn inherent_trait(&self) -> Option<Trait> {
589+
match self {
590+
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
591+
predicates.iter().find_map(|pred| match pred {
592+
GenericPredicate::Implemented(tr) => Some(tr.trait_),
593+
_ => None,
594+
})
595+
}
596+
_ => None,
597+
}
598+
}
532599
}
533600

534601
impl HirDisplay for &Ty {
@@ -669,21 +736,45 @@ impl HirDisplay for Ty {
669736
Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?,
670737
Ty::Param { name, .. } => write!(f, "{}", name)?,
671738
Ty::Bound(idx) => write!(f, "?{}", idx)?,
739+
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
740+
match self {
741+
Ty::Dyn(_) => write!(f, "dyn ")?,
742+
Ty::Opaque(_) => write!(f, "impl ")?,
743+
_ => unreachable!(),
744+
};
745+
// looping by hand here just to format the bounds in a slightly nicer way
746+
let mut first = true;
747+
for p in predicates.iter() {
748+
if !first {
749+
write!(f, " + ")?;
750+
}
751+
first = false;
752+
match p {
753+
// don't show the $0 self type
754+
GenericPredicate::Implemented(trait_ref) => {
755+
trait_ref.hir_fmt_ext(f, false)?
756+
}
757+
GenericPredicate::Error => p.hir_fmt(f)?,
758+
}
759+
}
760+
}
672761
Ty::Unknown => write!(f, "{{unknown}}")?,
673762
Ty::Infer(..) => write!(f, "_")?,
674763
}
675764
Ok(())
676765
}
677766
}
678767

679-
impl HirDisplay for TraitRef {
680-
fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
681-
write!(
682-
f,
683-
"{}: {}",
684-
self.substs[0].display(f.db),
685-
self.trait_.name(f.db).unwrap_or_else(Name::missing)
686-
)?;
768+
impl TraitRef {
769+
fn hir_fmt_ext(
770+
&self,
771+
f: &mut HirFormatter<impl HirDatabase>,
772+
with_self_ty: bool,
773+
) -> fmt::Result {
774+
if with_self_ty {
775+
write!(f, "{}: ", self.substs[0].display(f.db),)?;
776+
}
777+
write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?;
687778
if self.substs.len() > 1 {
688779
write!(f, "<")?;
689780
f.write_joined(&self.substs[1..], ", ")?;
@@ -693,6 +784,28 @@ impl HirDisplay for TraitRef {
693784
}
694785
}
695786

787+
impl HirDisplay for TraitRef {
788+
fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
789+
self.hir_fmt_ext(f, true)
790+
}
791+
}
792+
793+
impl HirDisplay for &GenericPredicate {
794+
fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
795+
HirDisplay::hir_fmt(*self, f)
796+
}
797+
}
798+
799+
impl HirDisplay for GenericPredicate {
800+
fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
801+
match self {
802+
GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
803+
GenericPredicate::Error => write!(f, "{{error}}")?,
804+
}
805+
Ok(())
806+
}
807+
}
808+
696809
impl HirDisplay for Obligation {
697810
fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
698811
match self {

crates/ra_hir/src/ty/lower.rs

+54-11
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
path::{GenericArg, PathSegment},
1818
resolve::{Resolution, Resolver},
1919
ty::AdtDef,
20-
type_ref::TypeRef,
20+
type_ref::{TypeBound, TypeRef},
2121
BuiltinType, Const, Enum, EnumVariant, Function, HirDatabase, ModuleDef, Path, Static, Struct,
2222
StructField, Trait, TypeAlias, Union,
2323
};
@@ -58,6 +58,22 @@ impl Ty {
5858
let sig = Substs(inner_tys.into());
5959
Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig)
6060
}
61+
TypeRef::DynTrait(bounds) => {
62+
let self_ty = Ty::Bound(0);
63+
let predicates = bounds
64+
.iter()
65+
.map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()))
66+
.collect::<Vec<_>>();
67+
Ty::Dyn(predicates.into())
68+
}
69+
TypeRef::ImplTrait(bounds) => {
70+
let self_ty = Ty::Bound(0);
71+
let predicates = bounds
72+
.iter()
73+
.map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()))
74+
.collect::<Vec<_>>();
75+
Ty::Opaque(predicates.into())
76+
}
6177
TypeRef::Error => Ty::Unknown,
6278
}
6379
}
@@ -310,13 +326,46 @@ impl TraitRef {
310326
TraitRef { trait_, substs }
311327
}
312328

313-
pub(crate) fn for_where_predicate(
329+
pub(crate) fn from_where_predicate(
314330
db: &impl HirDatabase,
315331
resolver: &Resolver,
316332
pred: &WherePredicate,
317333
) -> Option<TraitRef> {
318334
let self_ty = Ty::from_hir(db, resolver, &pred.type_ref);
319-
TraitRef::from_path(db, resolver, &pred.trait_ref, Some(self_ty))
335+
TraitRef::from_type_bound(db, resolver, &pred.bound, self_ty)
336+
}
337+
338+
pub(crate) fn from_type_bound(
339+
db: &impl HirDatabase,
340+
resolver: &Resolver,
341+
bound: &TypeBound,
342+
self_ty: Ty,
343+
) -> Option<TraitRef> {
344+
match bound {
345+
TypeBound::Path(path) => TraitRef::from_path(db, resolver, path, Some(self_ty)),
346+
TypeBound::Error => None,
347+
}
348+
}
349+
}
350+
351+
impl GenericPredicate {
352+
pub(crate) fn from_where_predicate(
353+
db: &impl HirDatabase,
354+
resolver: &Resolver,
355+
where_predicate: &WherePredicate,
356+
) -> GenericPredicate {
357+
TraitRef::from_where_predicate(db, &resolver, where_predicate)
358+
.map_or(GenericPredicate::Error, GenericPredicate::Implemented)
359+
}
360+
361+
pub(crate) fn from_type_bound(
362+
db: &impl HirDatabase,
363+
resolver: &Resolver,
364+
bound: &TypeBound,
365+
self_ty: Ty,
366+
) -> GenericPredicate {
367+
TraitRef::from_type_bound(db, &resolver, bound, self_ty)
368+
.map_or(GenericPredicate::Error, GenericPredicate::Implemented)
320369
}
321370
}
322371

@@ -376,10 +425,7 @@ pub(crate) fn trait_env(
376425
) -> Arc<super::TraitEnvironment> {
377426
let predicates = resolver
378427
.where_predicates_in_scope()
379-
.map(|pred| {
380-
TraitRef::for_where_predicate(db, &resolver, pred)
381-
.map_or(GenericPredicate::Error, GenericPredicate::Implemented)
382-
})
428+
.map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
383429
.collect::<Vec<_>>();
384430

385431
Arc::new(super::TraitEnvironment { predicates })
@@ -393,10 +439,7 @@ pub(crate) fn generic_predicates_query(
393439
let resolver = def.resolver(db);
394440
let predicates = resolver
395441
.where_predicates_in_scope()
396-
.map(|pred| {
397-
TraitRef::for_where_predicate(db, &resolver, pred)
398-
.map_or(GenericPredicate::Error, GenericPredicate::Implemented)
399-
})
442+
.map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
400443
.collect::<Vec<_>>();
401444
predicates.into()
402445
}

crates/ra_hir/src/ty/method_resolution.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,19 @@ fn iterate_trait_method_candidates<T>(
211211
let krate = resolver.krate()?;
212212
// FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
213213
let env = lower::trait_env(db, resolver);
214-
'traits: for t in resolver.traits_in_scope(db) {
214+
// if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
215+
let traits = ty.value.inherent_trait().into_iter().chain(resolver.traits_in_scope(db));
216+
'traits: for t in traits {
215217
let data = t.trait_data(db);
218+
219+
// FIXME this is a bit of a hack, since Chalk should say the same thing
220+
// anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
221+
let inherently_implemented = ty.value.inherent_trait() == Some(t);
222+
216223
// we'll be lazy about checking whether the type implements the
217224
// trait, but if we find out it doesn't, we'll skip the rest of the
218225
// iteration
219-
let mut known_implemented = false;
226+
let mut known_implemented = inherently_implemented;
220227
for item in data.items() {
221228
if let TraitItem::Function(m) = *item {
222229
let data = m.data(db);
@@ -271,6 +278,11 @@ pub(crate) fn implements_trait(
271278
krate: Crate,
272279
trait_: Trait,
273280
) -> bool {
281+
if ty.value.inherent_trait() == Some(trait_) {
282+
// FIXME this is a bit of a hack, since Chalk should say the same thing
283+
// anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
284+
return true;
285+
}
274286
let env = lower::trait_env(db, resolver);
275287
let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone());
276288
let solution = db.trait_solve(krate, goal);

0 commit comments

Comments
 (0)