Skip to content

Commit 6fb36df

Browse files
Merge #3145
3145: Make Self implement the trait inside trait default methods r=matklad a=flodiebold Co-authored-by: Florian Diebold <[email protected]>
2 parents 6711335 + 001dd6a commit 6fb36df

File tree

4 files changed

+78
-9
lines changed

4 files changed

+78
-9
lines changed

crates/ra_hir_def/src/resolver.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -542,11 +542,7 @@ impl Resolver {
542542

543543
fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver {
544544
let params = db.generic_params(def);
545-
if params.types.is_empty() {
546-
self
547-
} else {
548-
self.push_scope(Scope::GenericParams { def, params })
549-
}
545+
self.push_scope(Scope::GenericParams { def, params })
550546
}
551547

552548
fn push_impl_block_scope(self, impl_block: ImplId) -> Resolver {

crates/ra_hir_ty/src/lower.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ use hir_def::{
1414
path::{GenericArg, Path, PathSegment, PathSegments},
1515
resolver::{HasResolver, Resolver, TypeNs},
1616
type_ref::{TypeBound, TypeRef},
17-
AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
18-
LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
19-
VariantId,
17+
AdtId, AssocContainerId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule,
18+
ImplId, LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
19+
UnionId, VariantId,
2020
};
2121
use ra_arena::map::ArenaMap;
2222
use ra_db::CrateId;
@@ -672,11 +672,35 @@ impl TraitEnvironment {
672672
pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> {
673673
let ctx = TyLoweringContext::new(db, &resolver)
674674
.with_type_param_mode(TypeParamLoweringMode::Placeholder);
675-
let predicates = resolver
675+
let mut predicates = resolver
676676
.where_predicates_in_scope()
677677
.flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred))
678678
.collect::<Vec<_>>();
679679

680+
if let Some(def) = resolver.generic_def() {
681+
let container: Option<AssocContainerId> = match def {
682+
// FIXME: is there a function for this?
683+
GenericDefId::FunctionId(f) => Some(f.lookup(db).container),
684+
GenericDefId::AdtId(_) => None,
685+
GenericDefId::TraitId(_) => None,
686+
GenericDefId::TypeAliasId(t) => Some(t.lookup(db).container),
687+
GenericDefId::ImplId(_) => None,
688+
GenericDefId::EnumVariantId(_) => None,
689+
GenericDefId::ConstId(c) => Some(c.lookup(db).container),
690+
};
691+
if let Some(AssocContainerId::TraitId(trait_id)) = container {
692+
// add `Self: Trait<T1, T2, ...>` to the environment in trait
693+
// function default implementations (and hypothetical code
694+
// inside consts or type aliases)
695+
test_utils::tested_by!(trait_self_implements_self);
696+
let substs = Substs::type_params(db, trait_id);
697+
let trait_ref = TraitRef { trait_: trait_id, substs };
698+
let pred = GenericPredicate::Implemented(trait_ref);
699+
700+
predicates.push(pred);
701+
}
702+
}
703+
680704
Arc::new(TraitEnvironment { predicates })
681705
}
682706
}

crates/ra_hir_ty/src/marks.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ test_utils::marks!(
66
type_var_resolves_to_int_var
77
match_ergonomics_ref
88
coerce_merge_fail_fallback
9+
trait_self_implements_self
910
);

crates/ra_hir_ty/src/tests/traits.rs

+48
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,54 @@ fn test() {
299299
);
300300
}
301301

302+
#[test]
303+
fn trait_default_method_self_bound_implements_trait() {
304+
test_utils::covers!(trait_self_implements_self);
305+
assert_snapshot!(
306+
infer(r#"
307+
trait Trait {
308+
fn foo(&self) -> i64;
309+
fn bar(&self) -> {
310+
let x = self.foo();
311+
}
312+
}
313+
"#),
314+
@r###"
315+
[27; 31) 'self': &Self
316+
[53; 57) 'self': &Self
317+
[62; 97) '{ ... }': ()
318+
[76; 77) 'x': i64
319+
[80; 84) 'self': &Self
320+
[80; 90) 'self.foo()': i64
321+
"###
322+
);
323+
}
324+
325+
#[test]
326+
fn trait_default_method_self_bound_implements_super_trait() {
327+
test_utils::covers!(trait_self_implements_self);
328+
assert_snapshot!(
329+
infer(r#"
330+
trait SuperTrait {
331+
fn foo(&self) -> i64;
332+
}
333+
trait Trait: SuperTrait {
334+
fn bar(&self) -> {
335+
let x = self.foo();
336+
}
337+
}
338+
"#),
339+
@r###"
340+
[32; 36) 'self': &Self
341+
[86; 90) 'self': &Self
342+
[95; 130) '{ ... }': ()
343+
[109; 110) 'x': i64
344+
[113; 117) 'self': &Self
345+
[113; 123) 'self.foo()': i64
346+
"###
347+
);
348+
}
349+
302350
#[test]
303351
fn infer_project_associated_type() {
304352
// y, z, a don't yet work because of https://github.com/rust-lang/chalk/issues/234

0 commit comments

Comments
 (0)