Skip to content

Commit

Permalink
Merge #3145
Browse files Browse the repository at this point in the history
3145: Make Self implement the trait inside trait default methods r=matklad a=flodiebold



Co-authored-by: Florian Diebold <[email protected]>
  • Loading branch information
bors[bot] and flodiebold authored Feb 14, 2020
2 parents 6711335 + 001dd6a commit 6fb36df
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 9 deletions.
6 changes: 1 addition & 5 deletions crates/ra_hir_def/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,11 +542,7 @@ impl Resolver {

fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver {
let params = db.generic_params(def);
if params.types.is_empty() {
self
} else {
self.push_scope(Scope::GenericParams { def, params })
}
self.push_scope(Scope::GenericParams { def, params })
}

fn push_impl_block_scope(self, impl_block: ImplId) -> Resolver {
Expand Down
32 changes: 28 additions & 4 deletions crates/ra_hir_ty/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use hir_def::{
path::{GenericArg, Path, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs},
type_ref::{TypeBound, TypeRef},
AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
VariantId,
AdtId, AssocContainerId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule,
ImplId, LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
UnionId, VariantId,
};
use ra_arena::map::ArenaMap;
use ra_db::CrateId;
Expand Down Expand Up @@ -672,11 +672,35 @@ impl TraitEnvironment {
pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> {
let ctx = TyLoweringContext::new(db, &resolver)
.with_type_param_mode(TypeParamLoweringMode::Placeholder);
let predicates = resolver
let mut predicates = resolver
.where_predicates_in_scope()
.flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred))
.collect::<Vec<_>>();

if let Some(def) = resolver.generic_def() {
let container: Option<AssocContainerId> = match def {
// FIXME: is there a function for this?
GenericDefId::FunctionId(f) => Some(f.lookup(db).container),
GenericDefId::AdtId(_) => None,
GenericDefId::TraitId(_) => None,
GenericDefId::TypeAliasId(t) => Some(t.lookup(db).container),
GenericDefId::ImplId(_) => None,
GenericDefId::EnumVariantId(_) => None,
GenericDefId::ConstId(c) => Some(c.lookup(db).container),
};
if let Some(AssocContainerId::TraitId(trait_id)) = container {
// add `Self: Trait<T1, T2, ...>` to the environment in trait
// function default implementations (and hypothetical code
// inside consts or type aliases)
test_utils::tested_by!(trait_self_implements_self);
let substs = Substs::type_params(db, trait_id);
let trait_ref = TraitRef { trait_: trait_id, substs };
let pred = GenericPredicate::Implemented(trait_ref);

predicates.push(pred);
}
}

Arc::new(TraitEnvironment { predicates })
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/ra_hir_ty/src/marks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ test_utils::marks!(
type_var_resolves_to_int_var
match_ergonomics_ref
coerce_merge_fail_fallback
trait_self_implements_self
);
48 changes: 48 additions & 0 deletions crates/ra_hir_ty/src/tests/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,54 @@ fn test() {
);
}

#[test]
fn trait_default_method_self_bound_implements_trait() {
test_utils::covers!(trait_self_implements_self);
assert_snapshot!(
infer(r#"
trait Trait {
fn foo(&self) -> i64;
fn bar(&self) -> {
let x = self.foo();
}
}
"#),
@r###"
[27; 31) 'self': &Self
[53; 57) 'self': &Self
[62; 97) '{ ... }': ()
[76; 77) 'x': i64
[80; 84) 'self': &Self
[80; 90) 'self.foo()': i64
"###
);
}

#[test]
fn trait_default_method_self_bound_implements_super_trait() {
test_utils::covers!(trait_self_implements_self);
assert_snapshot!(
infer(r#"
trait SuperTrait {
fn foo(&self) -> i64;
}
trait Trait: SuperTrait {
fn bar(&self) -> {
let x = self.foo();
}
}
"#),
@r###"
[32; 36) 'self': &Self
[86; 90) 'self': &Self
[95; 130) '{ ... }': ()
[109; 110) 'x': i64
[113; 117) 'self': &Self
[113; 123) 'self.foo()': i64
"###
);
}

#[test]
fn infer_project_associated_type() {
// y, z, a don't yet work because of https://github.com/rust-lang/chalk/issues/234
Expand Down

0 comments on commit 6fb36df

Please sign in to comment.