Skip to content

Commit caa7ab5

Browse files
committed
Auto merge of #601 - memoryleak47:extern, r=jackh726
Extern types Closes #595.
2 parents 46344c8 + 404bc7e commit caa7ab5

File tree

15 files changed

+153
-8
lines changed

15 files changed

+153
-8
lines changed

chalk-integration/src/lowering.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use crate::interner::{ChalkFnAbi, ChalkIr};
22
use chalk_ir::cast::{Cast, Caster};
33
use chalk_ir::interner::{HasInterner, Interner};
44
use chalk_ir::{
5-
self, AdtId, AssocTypeId, BoundVar, ClausePriority, ClosureId, DebruijnIndex, FnDefId, ImplId,
6-
OpaqueTyId, QuantifiedWhereClauses, Substitution, ToGenericArg, TraitId, TyKind, VariableKinds,
5+
self, AdtId, AssocTypeId, BoundVar, ClausePriority, ClosureId, DebruijnIndex, FnDefId,
6+
ForeignDefId, ImplId, OpaqueTyId, QuantifiedWhereClauses, Substitution, ToGenericArg, TraitId,
7+
TyKind, VariableKinds,
78
};
89
use chalk_parse::ast::*;
910
use chalk_solve::rust_ir::{
@@ -33,6 +34,7 @@ type OpaqueTyKinds = BTreeMap<chalk_ir::OpaqueTyId<ChalkIr>, TypeKind>;
3334
type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId<ChalkIr>, Ident), AssociatedTyLookup>;
3435
type AssociatedTyValueIds =
3536
BTreeMap<(chalk_ir::ImplId<ChalkIr>, Ident), AssociatedTyValueId<ChalkIr>>;
37+
type ForeignIds = BTreeMap<Ident, chalk_ir::ForeignDefId<ChalkIr>>;
3638

3739
type ParameterMap = BTreeMap<Ident, chalk_ir::WithKind<ChalkIr, BoundVar>>;
3840

@@ -53,6 +55,7 @@ struct Env<'k> {
5355
opaque_ty_kinds: &'k OpaqueTyKinds,
5456
associated_ty_lookups: &'k AssociatedTyLookups,
5557
auto_traits: &'k AutoTraits,
58+
foreign_ty_ids: &'k ForeignIds,
5659
/// GenericArg identifiers are used as keys, therefore
5760
/// all identifiers in an environment must be unique (no shadowing).
5861
parameter_map: ParameterMap,
@@ -177,6 +180,16 @@ impl<'k> Env<'k> {
177180
.cast(interner),
178181
);
179182
}
183+
184+
if let Some(id) = self.foreign_ty_ids.get(&name.str) {
185+
return Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
186+
name: chalk_ir::TypeName::Foreign(*id),
187+
substitution: chalk_ir::Substitution::empty(interner),
188+
})
189+
.intern(interner)
190+
.cast(interner));
191+
}
192+
180193
if let Some(_) = self.trait_ids.get(&name.str) {
181194
return Err(RustIrError::NotStruct(name.clone()));
182195
}
@@ -408,6 +421,7 @@ impl LowerProgram for Program {
408421
}
409422
Item::Impl(_) => continue,
410423
Item::Clause(_) => continue,
424+
Item::Foreign(_) => continue,
411425
};
412426
}
413427

@@ -425,6 +439,8 @@ impl LowerProgram for Program {
425439
let mut opaque_ty_data = BTreeMap::new();
426440
let mut hidden_opaque_types = BTreeMap::new();
427441
let mut custom_clauses = Vec::new();
442+
let mut foreign_ty_ids = BTreeMap::new();
443+
428444
for (item, &raw_id) in self.items.iter().zip(&raw_ids) {
429445
let empty_env = Env {
430446
adt_ids: &adt_ids,
@@ -441,6 +457,7 @@ impl LowerProgram for Program {
441457
associated_ty_lookups: &associated_ty_lookups,
442458
parameter_map: BTreeMap::new(),
443459
auto_traits: &auto_traits,
460+
foreign_ty_ids: &foreign_ty_ids,
444461
};
445462

446463
match *item {
@@ -638,6 +655,9 @@ impl LowerProgram for Program {
638655
);
639656
}
640657
}
658+
Item::Foreign(ForeignDefn(ref ident)) => {
659+
foreign_ty_ids.insert(ident.str.clone(), ForeignDefId(raw_id));
660+
}
641661
}
642662
}
643663

@@ -667,6 +687,7 @@ impl LowerProgram for Program {
667687
hidden_opaque_types,
668688
custom_clauses,
669689
object_safe_traits,
690+
foreign_ty_ids,
670691
};
671692

672693
Ok(program)
@@ -2016,6 +2037,7 @@ impl LowerGoal<LoweredProgram> for Goal {
20162037
trait_kinds: &program.trait_kinds,
20172038
opaque_ty_kinds: &program.opaque_ty_kinds,
20182039
associated_ty_lookups: &associated_ty_lookups,
2040+
foreign_ty_ids: &program.foreign_ty_ids,
20192041
parameter_map: BTreeMap::new(),
20202042
auto_traits: &auto_traits,
20212043
};

chalk-integration/src/program.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use chalk_ir::could_match::CouldMatch;
44
use chalk_ir::debug::Angle;
55
use chalk_ir::{
66
debug::SeparatorTraitRef, AdtId, AliasTy, ApplicationTy, AssocTypeId, Binders,
7-
CanonicalVarKinds, ClosureId, FnDefId, GenericArg, Goal, Goals, ImplId, Lifetime, OpaqueTy,
8-
OpaqueTyId, ProgramClause, ProgramClauseImplication, ProgramClauses, ProjectionTy,
7+
CanonicalVarKinds, ClosureId, FnDefId, ForeignDefId, GenericArg, Goal, Goals, ImplId, Lifetime,
8+
OpaqueTy, OpaqueTyId, ProgramClause, ProgramClauseImplication, ProgramClauses, ProjectionTy,
99
Substitution, TraitId, Ty,
1010
};
1111
use chalk_solve::rust_ir::{
@@ -89,6 +89,9 @@ pub struct Program {
8989

9090
/// Store the traits marked with `#[object_safe]`
9191
pub object_safe_traits: HashSet<TraitId<ChalkIr>>,
92+
93+
/// For each foreign type `extern { type A; }`
94+
pub foreign_ty_ids: BTreeMap<Identifier, ForeignDefId<ChalkIr>>,
9295
}
9396

9497
impl Program {

chalk-ir/src/debug.rs

+8
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ impl<I: Interner> Debug for ClosureId<I> {
3535
}
3636
}
3737

38+
impl<I: Interner> Debug for ForeignDefId<I> {
39+
fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
40+
I::debug_foreign_def_id(*self, fmt)
41+
.unwrap_or_else(|| write!(fmt, "ForeignDefId({:?})", self.0))
42+
}
43+
}
44+
3845
impl<I: Interner> Debug for Ty<I> {
3946
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
4047
I::debug_ty(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned))
@@ -184,6 +191,7 @@ impl<I: Interner> Debug for TypeName<I> {
184191
TypeName::Never => write!(fmt, "Never"),
185192
TypeName::Array => write!(fmt, "{{array}}"),
186193
TypeName::Closure(id) => write!(fmt, "{{closure:{:?}}}", id),
194+
TypeName::Foreign(foreign_ty) => write!(fmt, "{:?}", foreign_ty),
187195
TypeName::Error => write!(fmt, "{{error}}"),
188196
}
189197
}

chalk-ir/src/fold/boring_impls.rs

+1
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ id_fold!(AssocTypeId);
303303
id_fold!(OpaqueTyId);
304304
id_fold!(FnDefId);
305305
id_fold!(ClosureId);
306+
id_fold!(ForeignDefId);
306307

307308
impl<I: Interner, TI: TargetInterner<I>> SuperFold<I, TI> for ProgramClauseData<I> {
308309
fn super_fold_with<'i>(

chalk-ir/src/interner.rs

+11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::ClosureId;
99
use crate::Constraint;
1010
use crate::Constraints;
1111
use crate::FnDefId;
12+
use crate::ForeignDefId;
1213
use crate::GenericArg;
1314
use crate::GenericArgData;
1415
use crate::Goal;
@@ -245,6 +246,16 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash {
245246
None
246247
}
247248

249+
/// Prints the debug representation of a foreign-def-id.
250+
/// Returns `None` to fallback to the default debug output.
251+
#[allow(unused_variables)]
252+
fn debug_foreign_def_id(
253+
foreign_def_id: ForeignDefId<Self>,
254+
fmt: &mut fmt::Formatter<'_>,
255+
) -> Option<fmt::Result> {
256+
None
257+
}
258+
248259
/// Prints the debug representation of an alias.
249260
/// Returns `None` to fallback to the default debug output.
250261
#[allow(unused_variables)]

chalk-ir/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ pub enum TypeName<I: Interner> {
254254
/// A closure.
255255
Closure(ClosureId<I>),
256256

257+
/// foreign types
258+
Foreign(ForeignDefId<I>),
259+
257260
/// This can be used to represent an error, e.g. during name resolution of a type.
258261
/// Chalk itself will not produce this, just pass it through when given.
259262
Error,
@@ -363,6 +366,10 @@ pub struct FnDefId<I: Interner>(pub I::DefId);
363366
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
364367
pub struct ClosureId<I: Interner>(pub I::DefId);
365368

369+
/// Id for foreign types.
370+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
371+
pub struct ForeignDefId<I: Interner>(pub I::DefId);
372+
366373
impl_debugs!(ImplId, ClauseId);
367374

368375
/// A Rust type. The actual type data is stored in `TyData`.

chalk-ir/src/visit/boring_impls.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
77
use crate::{
88
AdtId, AssocTypeId, ClausePriority, ClosureId, Constraints, DebruijnIndex, FloatTy, FnDefId,
9-
GenericArg, Goals, ImplId, IntTy, Interner, Mutability, OpaqueTyId, PlaceholderIndex,
10-
ProgramClause, ProgramClauses, QuantifiedWhereClauses, QuantifierKind, Safety, Scalar,
11-
Substitution, SuperVisit, TraitId, UintTy, UniverseIndex, Visit, VisitResult, Visitor,
9+
ForeignDefId, GenericArg, Goals, ImplId, IntTy, Interner, Mutability, OpaqueTyId,
10+
PlaceholderIndex, ProgramClause, ProgramClauses, QuantifiedWhereClauses, QuantifierKind,
11+
Safety, Scalar, Substitution, SuperVisit, TraitId, UintTy, UniverseIndex, Visit, VisitResult,
12+
Visitor,
1213
};
1314
use std::{marker::PhantomData, sync::Arc};
1415

@@ -239,6 +240,7 @@ id_visit!(OpaqueTyId);
239240
id_visit!(AssocTypeId);
240241
id_visit!(FnDefId);
241242
id_visit!(ClosureId);
243+
id_visit!(ForeignDefId);
242244

243245
impl<I: Interner> SuperVisit<I> for ProgramClause<I> {
244246
fn super_visit_with<'i, R: VisitResult>(

chalk-parse/src/ast.rs

+4
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ pub enum Item {
2727
OpaqueTyDefn(OpaqueTyDefn),
2828
Impl(Impl),
2929
Clause(Clause),
30+
Foreign(ForeignDefn),
3031
}
3132

33+
#[derive(Clone, PartialEq, Eq, Debug)]
34+
pub struct ForeignDefn(pub Identifier);
35+
3236
#[derive(Clone, PartialEq, Eq, Debug)]
3337
pub struct AdtDefn {
3438
pub name: Identifier,

chalk-parse/src/parser.lalrpop

+5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ Item: Option<Item> = {
2020
OpaqueTyDefn => Some(Item::OpaqueTyDefn(<>)),
2121
Impl => Some(Item::Impl(<>)),
2222
Clause => Some(Item::Clause(<>)),
23+
ForeignType => Some(Item::Foreign(<>)),
24+
};
25+
26+
ForeignType: ForeignDefn = {
27+
"extern" "type" <id:Id> ";" => ForeignDefn(id),
2328
};
2429

2530
Comment: () = r"//.*";

chalk-solve/src/clauses.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,8 @@ fn match_type_name<I: Interner>(
635635
| TypeName::Ref(_)
636636
| TypeName::Array
637637
| TypeName::Never
638-
| TypeName::Closure(_) => {
638+
| TypeName::Closure(_)
639+
| TypeName::Foreign(_) => {
639640
builder.push_fact(WellFormed::Ty(application.clone().intern(interner)))
640641
}
641642
}

chalk-solve/src/clauses/builtin_traits/copy.rs

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ pub fn add_copy_program_clauses<I: Interner>(
7575
| TypeName::AssociatedType(_)
7676
| TypeName::Slice
7777
| TypeName::OpaqueType(_)
78+
| TypeName::Foreign(_)
7879
| TypeName::Error => {}
7980
},
8081

chalk-solve/src/clauses/builtin_traits/sized.rs

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub fn add_sized_program_clauses<I: Interner>(
9393
| TypeName::Slice
9494
| TypeName::OpaqueType(_)
9595
| TypeName::Str
96+
| TypeName::Foreign(_)
9697
| TypeName::Error => {}
9798
},
9899

chalk-solve/src/display/ty.rs

+1
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ impl<I: Interner> RenderAsRust<I> for ApplicationTy<I> {
217217
// FIXME: write out valid types for these variants
218218
TypeName::FnDef(_) => write!(f, "<fn_def>")?,
219219
TypeName::Closure(..) => write!(f, "<closure>")?,
220+
TypeName::Foreign(_) => write!(f, "<foreign>")?,
220221

221222
TypeName::Array => write!(
222223
f,

tests/test/foreign_types.rs

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//! Tests for foreign types
2+
3+
use super::*;
4+
5+
// foreign types don't implement any builtin traits
6+
#[test]
7+
fn foreign_ty_trait_impl() {
8+
test! {
9+
program {
10+
extern type A;
11+
trait Foo {}
12+
impl Foo for A {}
13+
}
14+
15+
goal { A: Foo } yields { "Unique" }
16+
}
17+
}
18+
19+
#[test]
20+
fn foreign_ty_lowering() {
21+
lowering_success! {
22+
program {
23+
extern type A;
24+
}
25+
}
26+
}
27+
28+
// foreign types are always well-formed
29+
#[test]
30+
fn foreign_ty_is_well_formed() {
31+
test! {
32+
program {
33+
extern type A;
34+
}
35+
36+
goal { WellFormed(A) } yields { "Unique" }
37+
}
38+
}
39+
40+
// foreign types don't implement any builtin traits
41+
#[test]
42+
fn foreign_ty_is_not_sized() {
43+
test! {
44+
program {
45+
#[lang(sized)] trait Sized {}
46+
extern type A;
47+
}
48+
49+
goal { not { A: Sized } } yields { "Unique" }
50+
}
51+
}
52+
53+
// foreign types don't implement any builtin traits
54+
#[test]
55+
fn foreign_ty_is_not_copy() {
56+
test! {
57+
program {
58+
#[lang(copy)] trait Copy {}
59+
extern type A;
60+
}
61+
62+
goal { not { A: Copy } } yields { "Unique" }
63+
}
64+
}
65+
66+
// foreign types don't implement any builtin traits
67+
#[test]
68+
fn foreign_ty_is_not_clone() {
69+
test! {
70+
program {
71+
#[lang(clone)] trait Clone {}
72+
extern type A;
73+
}
74+
75+
goal { not { A: Clone } } yields { "Unique" }
76+
}
77+
}

tests/test/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ mod constants;
329329
mod cycle;
330330
mod existential_types;
331331
mod fn_def;
332+
mod foreign_types;
332333
mod implied_bounds;
333334
mod impls;
334335
mod misc;

0 commit comments

Comments
 (0)