Skip to content

Commit 4866423

Browse files
authored
Merge pull request #385 from Areredify/copy2
add `Copy`, `Clone` and `Drop` traits support
2 parents 154020e + 9b0ffb4 commit 4866423

File tree

14 files changed

+472
-63
lines changed

14 files changed

+472
-63
lines changed

chalk-integration/src/db.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
138138
.impl_provided_for(auto_trait_id, struct_id)
139139
}
140140

141-
fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> TraitId<ChalkIr> {
141+
fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> Option<TraitId<ChalkIr>> {
142142
self.program_ir()
143143
.unwrap()
144144
.well_known_trait_id(well_known_trait)

chalk-integration/src/lowering.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,9 @@ impl LowerWellKnownTrait for WellKnownTrait {
13671367
fn lower(&self) -> rust_ir::WellKnownTrait {
13681368
match self {
13691369
Self::SizedTrait => rust_ir::WellKnownTrait::SizedTrait,
1370+
Self::CopyTrait => rust_ir::WellKnownTrait::CopyTrait,
1371+
Self::CloneTrait => rust_ir::WellKnownTrait::CloneTrait,
1372+
Self::DropTrait => rust_ir::WellKnownTrait::DropTrait,
13701373
}
13711374
}
13721375
}

chalk-integration/src/program.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -321,11 +321,8 @@ impl RustIrDatabase<ChalkIr> for Program {
321321
})
322322
}
323323

324-
fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> TraitId<ChalkIr> {
325-
*self
326-
.well_known_traits
327-
.get(&well_known_trait)
328-
.unwrap_or_else(|| panic!("No lang item found for {:?}", well_known_trait))
324+
fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> Option<TraitId<ChalkIr>> {
325+
self.well_known_traits.get(&well_known_trait).map(|x| *x)
329326
}
330327

331328
fn interner(&self) -> &ChalkIr {

chalk-parse/src/ast.rs

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub struct TraitDefn {
5454
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
5555
pub enum WellKnownTrait {
5656
SizedTrait,
57+
CopyTrait,
58+
CloneTrait,
59+
DropTrait,
5760
}
5861

5962
#[derive(Clone, PartialEq, Eq, Debug)]

chalk-parse/src/parser.lalrpop

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ CoinductiveKeyword: () = "#" "[" "coinductive" "]";
4545

4646
WellKnownTrait: WellKnownTrait = {
4747
"#" "[" "lang" "(" "sized" ")" "]" => WellKnownTrait::SizedTrait,
48+
"#" "[" "lang" "(" "copy" ")" "]" => WellKnownTrait::CopyTrait,
49+
"#" "[" "lang" "(" "clone" ")" "]" => WellKnownTrait::CloneTrait,
50+
"#" "[" "lang" "(" "drop" ")" "]" => WellKnownTrait::DropTrait,
4851
};
4952

5053
StructDefn: StructDefn = {

chalk-rust-ir/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ pub enum WellKnownTrait {
136136
SizedTrait,
137137
CopyTrait,
138138
CloneTrait,
139+
DropTrait,
139140
}
140141

141142
impl<I: Interner> TraitDatum<I> {

chalk-solve/src/clauses/builtin_traits.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use super::builder::ClauseBuilder;
22
use crate::{Interner, RustIrDatabase, TraitRef, WellKnownTrait};
33
use chalk_ir::TyData;
44

5+
mod clone;
6+
mod copy;
57
mod sized;
68

79
/// For well known traits we have special hard-coded impls, either as an
@@ -22,7 +24,9 @@ pub fn add_builtin_program_clauses<I: Interner>(
2224

2325
match well_known {
2426
WellKnownTrait::SizedTrait => sized::add_sized_program_clauses(db, builder, trait_ref, ty),
25-
WellKnownTrait::CopyTrait => { /* TODO */ }
26-
WellKnownTrait::CloneTrait => { /* TODO */ }
27+
WellKnownTrait::CopyTrait => copy::add_copy_program_clauses(db, builder, trait_ref, ty),
28+
WellKnownTrait::CloneTrait => clone::add_clone_program_clauses(db, builder, trait_ref, ty),
29+
// Drop impls are provided explicitly
30+
WellKnownTrait::DropTrait => (),
2731
}
2832
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use crate::clauses::ClauseBuilder;
2+
use crate::{Interner, RustIrDatabase, TraitRef};
3+
use chalk_ir::TyData;
4+
5+
use super::copy::add_copy_program_clauses;
6+
7+
pub fn add_clone_program_clauses<I: Interner>(
8+
db: &dyn RustIrDatabase<I>,
9+
builder: &mut ClauseBuilder<'_, I>,
10+
trait_ref: &TraitRef<I>,
11+
ty: &TyData<I>,
12+
) {
13+
let _interner = db.interner();
14+
15+
// Implement Clone for types that automaticly implement Copy
16+
add_copy_program_clauses(db, builder, trait_ref, ty);
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use crate::clauses::ClauseBuilder;
2+
use crate::{Interner, RustIrDatabase, TraitRef};
3+
use chalk_ir::TyData;
4+
5+
pub fn add_copy_program_clauses<I: Interner>(
6+
db: &dyn RustIrDatabase<I>,
7+
builder: &mut ClauseBuilder<'_, I>,
8+
trait_ref: &TraitRef<I>,
9+
ty: &TyData<I>,
10+
) {
11+
let _interner = db.interner();
12+
13+
match ty {
14+
TyData::Function(_) => builder.push_fact(trait_ref.clone()),
15+
// TODO(areredify)
16+
// when #368 lands, extend this to handle everything accordingly
17+
_ => return,
18+
};
19+
}

chalk-solve/src/clauses/program_clauses.rs

+26-17
Original file line numberDiff line numberDiff line change
@@ -415,23 +415,32 @@ impl<I: Interner> ToProgramClauses<I> for TraitDatum<I> {
415415
// conditions.
416416
let type_parameters: Vec<_> = trait_ref.type_parameters(interner).collect();
417417

418-
// Add all cases for potential downstream impls that could exist
419-
for i in 0..type_parameters.len() {
420-
builder.push_clause(
421-
trait_ref.clone(),
422-
where_clauses
423-
.iter()
424-
.cloned()
425-
.casted(interner)
426-
.chain(iter::once(DomainGoal::Compatible(()).cast(interner)))
427-
.chain((0..i).map(|j| {
428-
DomainGoal::IsFullyVisible(type_parameters[j].clone()).cast(interner)
429-
}))
430-
.chain(iter::once(
431-
DomainGoal::DownstreamType(type_parameters[i].clone()).cast(interner),
432-
))
433-
.chain(iter::once(GoalData::CannotProve(()).intern(interner))),
434-
);
418+
// Drop trait can't have downstream implementation because it can only
419+
// be implemented with the same genericity as the struct definition,
420+
// i.e. Drop implementation for `struct S<T: Eq> {}` is forced to be
421+
// `impl Drop<T: Eq> for S<T> { ... }`. That means that orphan rules
422+
// prevent Drop from being implemented in downstream crates.
423+
if self.well_known != Some(WellKnownTrait::DropTrait) {
424+
// Add all cases for potential downstream impls that could exist
425+
for i in 0..type_parameters.len() {
426+
builder.push_clause(
427+
trait_ref.clone(),
428+
where_clauses
429+
.iter()
430+
.cloned()
431+
.casted(interner)
432+
.chain(iter::once(DomainGoal::Compatible(()).cast(interner)))
433+
.chain((0..i).map(|j| {
434+
DomainGoal::IsFullyVisible(type_parameters[j].clone())
435+
.cast(interner)
436+
}))
437+
.chain(iter::once(
438+
DomainGoal::DownstreamType(type_parameters[i].clone())
439+
.cast(interner),
440+
))
441+
.chain(iter::once(GoalData::CannotProve(()).intern(interner))),
442+
);
443+
}
435444
}
436445

437446
// Orphan rules:

chalk-solve/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ pub trait RustIrDatabase<I: Interner>: Debug {
8181
}
8282

8383
/// Returns id of a trait lang item, if found
84-
fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> TraitId<I>;
84+
fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> Option<TraitId<I>>;
8585

8686
fn interner(&self) -> &I;
8787
}

0 commit comments

Comments
 (0)