Skip to content

Commit 0bd867e

Browse files
committed
Add ObjectSafe goal and flag
1 parent 582ea06 commit 0bd867e

File tree

14 files changed

+80
-14
lines changed

14 files changed

+80
-14
lines changed

chalk-integration/src/db.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,10 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
156156
fn interner(&self) -> &ChalkIr {
157157
&ChalkIr
158158
}
159+
160+
fn is_object_safe(&self, trait_id: TraitId<ChalkIr>) -> bool {
161+
self.program_ir()
162+
.unwrap()
163+
.is_object_safe(trait_id)
164+
}
159165
}

chalk-integration/src/lowering.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,9 @@ impl LowerDomainGoal for DomainGoal {
758758
vec![chalk_ir::DomainGoal::DownstreamType(ty.lower(env)?)]
759759
}
760760
DomainGoal::Reveal => vec![chalk_ir::DomainGoal::Reveal(())],
761+
DomainGoal::ObjectSafe { id } => {
762+
vec![chalk_ir::DomainGoal::ObjectSafe(env.lookup_trait(id)?)]
763+
}
761764
};
762765
Ok(goals)
763766
}
@@ -1016,6 +1019,7 @@ impl LowerTraitFlags for TraitFlags {
10161019
fundamental: self.fundamental,
10171020
non_enumerable: self.non_enumerable,
10181021
coinductive: self.coinductive,
1022+
object_safe: self.object_safe,
10191023
}
10201024
}
10211025
}

chalk-integration/src/program.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,4 +392,8 @@ impl RustIrDatabase<ChalkIr> for Program {
392392
fn interner(&self) -> &ChalkIr {
393393
&ChalkIr
394394
}
395+
396+
fn is_object_safe(&self, trait_id: TraitId<ChalkIr>) -> bool {
397+
self.trait_datum(trait_id).is_object_safe_trait()
398+
}
395399
}

chalk-ir/src/debug.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ impl<I: Interner> Debug for DomainGoal<I> {
628628
DomainGoal::Compatible(_) => write!(fmt, "Compatible"),
629629
DomainGoal::DownstreamType(n) => write!(fmt, "DownstreamType({:?})", n),
630630
DomainGoal::Reveal(_) => write!(fmt, "Reveal"),
631+
DomainGoal::ObjectSafe(n) => write!(fmt, "ObjectSafe({:?})", n)
631632
}
632633
}
633634
}

chalk-ir/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,9 @@ pub enum DomainGoal<I: Interner> {
10881088
/// Used to activate the "reveal mode", in which opaque (`impl Trait`) types can be equated
10891089
/// to their actual type.
10901090
Reveal(()),
1091+
1092+
/// Used to indicate that a trait is object safe.
1093+
ObjectSafe(TraitId<I>),
10911094
}
10921095

10931096
pub type QuantifiedWhereClause<I> = Binders<WhereClause<I>>;

chalk-parse/src/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub struct TraitFlags {
6868
pub fundamental: bool,
6969
pub non_enumerable: bool,
7070
pub coinductive: bool,
71+
pub object_safe: bool,
7172
}
7273

7374
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -315,6 +316,7 @@ pub enum DomainGoal {
315316
Compatible,
316317
DownstreamType { ty: Ty },
317318
Reveal,
319+
ObjectSafe { id: Identifier }
318320
}
319321

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

chalk-parse/src/parser.lalrpop

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ MarkerKeyword: () = "#" "[" "marker" "]";
4343
FundamentalKeyword: () = "#" "[" "fundamental" "]";
4444
NonEnumerableKeyword: () = "#" "[" "non_enumerable" "]";
4545
CoinductiveKeyword: () = "#" "[" "coinductive" "]";
46+
ObjectSafeKeyword: () = "#" "[" "object_safe" "]";
4647

4748
WellKnownTrait: WellKnownTrait = {
4849
"#" "[" "lang" "(" "sized" ")" "]" => WellKnownTrait::SizedTrait,
@@ -67,7 +68,7 @@ StructDefn: StructDefn = {
6768
};
6869

6970
TraitDefn: TraitDefn = {
70-
<auto:AutoKeyword?> <marker:MarkerKeyword?> <upstream:UpstreamKeyword?> <fundamental:FundamentalKeyword?> <non_enumerable:NonEnumerableKeyword?> <coinductive:CoinductiveKeyword?> <well_known:WellKnownTrait?> "trait" <n:Id><p:Angle<ParameterKind>>
71+
<auto:AutoKeyword?> <marker:MarkerKeyword?> <upstream:UpstreamKeyword?> <fundamental:FundamentalKeyword?> <non_enumerable:NonEnumerableKeyword?> <coinductive:CoinductiveKeyword?> <object_safe:ObjectSafeKeyword?> <well_known:WellKnownTrait?> "trait" <n:Id><p:Angle<ParameterKind>>
7172
<w:QuantifiedWhereClauses> "{" <a:AssocTyDefn*> "}" => TraitDefn
7273
{
7374
name: n,
@@ -82,6 +83,7 @@ TraitDefn: TraitDefn = {
8283
fundamental: fundamental.is_some(),
8384
non_enumerable: non_enumerable.is_some(),
8485
coinductive: coinductive.is_some(),
86+
object_safe: object_safe.is_some(),
8587
},
8688
}
8789
};
@@ -365,6 +367,8 @@ DomainGoal: DomainGoal = {
365367
"DownstreamType" "(" <ty:Ty> ")" => DomainGoal::DownstreamType { ty },
366368

367369
"Reveal" => DomainGoal::Reveal,
370+
371+
"ObjectSafe" "(" <id:Id> ")" => DomainGoal::ObjectSafe { id }
368372
};
369373

370374
LeafGoal: LeafGoal = {

chalk-rust-ir/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ impl<I: Interner> TraitDatum<I> {
168168
self.flags.coinductive
169169
}
170170

171+
pub fn is_object_safe_trait(&self) -> bool {
172+
self.flags.object_safe
173+
}
174+
171175
/// Gives access to the where clauses of the trait, quantified over the type parameters of the trait:
172176
///
173177
/// ```ignore
@@ -221,6 +225,9 @@ pub struct TraitFlags {
221225
pub non_enumerable: bool,
222226

223227
pub coinductive: bool,
228+
229+
/// Indicates that a trait is object safe
230+
pub object_safe: bool,
224231
}
225232

226233
/// An inline bound, e.g. `: Foo<K>` in `impl<K, T: Foo<K>> SomeType<T>`.

chalk-solve/src/clauses.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -244,16 +244,17 @@ fn program_clauses_that_could_match<I: Interner>(
244244
.opaque_ty_data(opaque_ty.opaque_ty_id)
245245
.to_program_clauses(builder),
246246
},
247-
DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
248-
db.trait_datum(trait_predicate.trait_id)
247+
DomainGoal::WellFormed(WellFormed::Trait(trait_ref))
248+
| DomainGoal::LocalImplAllowed(trait_ref) => {
249+
db.trait_datum(trait_ref.trait_id)
249250
.to_program_clauses(builder);
250251
}
252+
DomainGoal::ObjectSafe(trait_id) => db.trait_datum(*trait_id).to_program_clauses(builder),
251253
DomainGoal::WellFormed(WellFormed::Ty(ty))
252254
| DomainGoal::IsUpstream(ty)
253-
| DomainGoal::DownstreamType(ty) => match_ty(builder, environment, ty)?,
254-
DomainGoal::IsFullyVisible(ty) | DomainGoal::IsLocal(ty) => {
255-
match_ty(builder, environment, ty)?
256-
}
255+
| DomainGoal::DownstreamType(ty)
256+
| DomainGoal::IsFullyVisible(ty)
257+
| DomainGoal::IsLocal(ty) => match_ty(builder, environment, ty)?,
257258
DomainGoal::FromEnv(_) => (), // Computed in the environment
258259
DomainGoal::Normalize(Normalize { alias, ty: _ }) => match alias {
259260
AliasTy::Projection(proj) => {
@@ -291,11 +292,7 @@ fn program_clauses_that_could_match<I: Interner>(
291292
}
292293
AliasTy::Opaque(_) => (),
293294
},
294-
DomainGoal::LocalImplAllowed(trait_ref) => db
295-
.trait_datum(trait_ref.trait_id)
296-
.to_program_clauses(builder),
297-
DomainGoal::Compatible(()) => (),
298-
DomainGoal::Reveal(()) => (),
295+
DomainGoal::Compatible(()) | DomainGoal::Reveal(()) => (),
299296
};
300297

301298
Ok(())

chalk-solve/src/clauses/program_clauses.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,11 @@ impl<I: Interner> ToProgramClauses<I> for TraitDatum<I> {
540540
);
541541
}
542542

543+
// Object safety check
544+
if builder.db.is_object_safe(trait_ref.trait_id) {
545+
builder.push_fact(DomainGoal::ObjectSafe(trait_ref.trait_id));
546+
}
547+
543548
// Reverse implied bound rules: given (e.g.) `trait Foo: Bar + Baz`,
544549
// we create rules like:
545550
//

0 commit comments

Comments
 (0)