Skip to content

Commit 91da1a5

Browse files
committed
Write an initial version of the program_clauses callback
1 parent 74ff7dc commit 91da1a5

File tree

3 files changed

+214
-25
lines changed

3 files changed

+214
-25
lines changed

src/librustc_traits/chalk_context.rs

+207-21
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ use rustc::traits::{
2323
Goal,
2424
GoalKind,
2525
Clause,
26+
ProgramClauseCategory,
2627
QuantifierKind,
2728
Environment,
2829
InEnvironment,
2930
};
3031
use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
3132
use rustc::ty::subst::Kind;
3233
use rustc::ty::{self, TyCtxt};
34+
use rustc::hir::def_id::DefId;
3335

3436
use std::fmt::{self, Debug};
3537
use std::marker::PhantomData;
@@ -330,46 +332,230 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
330332
{
331333
fn program_clauses(
332334
&self,
333-
_environment: &Environment<'tcx>,
335+
environment: &Environment<'tcx>,
334336
goal: &DomainGoal<'tcx>,
335337
) -> Vec<Clause<'tcx>> {
336338
use rustc::traits::WhereClause::*;
337339

338-
match goal {
339-
DomainGoal::Holds(Implemented(_trait_predicate)) => {
340+
fn assemble_clauses_from_impls<'tcx>(
341+
tcx: ty::TyCtxt<'_, '_, 'tcx>,
342+
trait_def_id: DefId,
343+
clauses: &mut Vec<Clause<'tcx>>
344+
) {
345+
tcx.for_each_impl(trait_def_id, |impl_def_id| {
346+
clauses.extend(
347+
tcx.program_clauses_for(impl_def_id)
348+
.into_iter()
349+
.cloned()
350+
);
351+
});
352+
}
353+
354+
fn assemble_clauses_from_assoc_ty_values<'tcx>(
355+
tcx: ty::TyCtxt<'_, '_, 'tcx>,
356+
trait_def_id: DefId,
357+
clauses: &mut Vec<Clause<'tcx>>
358+
) {
359+
tcx.for_each_impl(trait_def_id, |impl_def_id| {
360+
for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
361+
clauses.extend(
362+
tcx.program_clauses_for(*def_id)
363+
.into_iter()
364+
.cloned()
365+
);
366+
}
367+
});
368+
}
369+
370+
let mut clauses = match goal {
371+
DomainGoal::Holds(Implemented(trait_predicate)) => {
372+
// These come from:
373+
// * implementations of the trait itself (rule `Implemented-From-Impl`)
374+
// * the trait decl (rule `Implemented-From-Env`)
375+
376+
let mut clauses = vec![];
377+
assemble_clauses_from_impls(
378+
self.infcx.tcx,
379+
trait_predicate.def_id(),
380+
&mut clauses
381+
);
382+
383+
// FIXME: we need to add special rules for builtin impls:
384+
// * `Copy` / `Clone`
385+
// * `Sized`
386+
// * `Unsize`
387+
// * `Generator`
388+
// * `FnOnce` / `FnMut` / `Fn`
389+
// * trait objects
390+
// * auto traits
391+
392+
// Rule `Implemented-From-Env` will be computed from the environment.
393+
clauses
394+
}
395+
396+
DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
397+
// These come from:
398+
// * the assoc type definition (rule `ProjectionEq-Placeholder`)
399+
// * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
400+
// * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
401+
// * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
402+
403+
let clauses = self.infcx.tcx.program_clauses_for(
404+
projection_predicate.projection_ty.item_def_id
405+
).into_iter()
406+
407+
// only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
408+
.filter(|clause| clause.category() == ProgramClauseCategory::Other)
409+
410+
.cloned()
411+
.collect::<Vec<_>>();
412+
413+
// Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
414+
// from the environment.
415+
clauses
416+
}
417+
418+
DomainGoal::Holds(RegionOutlives(..)) => {
340419
// These come from:
341-
//
342-
// - Trait definitions (implied bounds)
343-
// - Implementations of the trait itself
344-
panic!()
420+
// * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
421+
// * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
422+
423+
// All of these rules are computed in the environment.
424+
vec![]
345425
}
346426

347-
DomainGoal::Holds(ProjectionEq(_projection_predicate)) => {
427+
DomainGoal::Holds(TypeOutlives(..)) => {
348428
// These come from:
349-
panic!()
429+
// * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
430+
// * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
431+
432+
// All of these rules are computed in the environment.
433+
vec![]
350434
}
351435

352-
DomainGoal::Holds(RegionOutlives(_region_outlives)) => {
353-
panic!()
436+
DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
437+
// These come from -- the trait decl (rule `WellFormed-TraitRef`).
438+
self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
439+
.into_iter()
440+
441+
// only select `WellFormed-TraitRef`
442+
.filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
443+
444+
.cloned()
445+
.collect()
354446
}
355447

356-
DomainGoal::Holds(TypeOutlives(_type_outlives)) => {
357-
panic!()
448+
DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
449+
// These come from:
450+
// * the associated type definition if `ty` refers to an unnormalized
451+
// associated type (rule `WellFormed-AssocTy`)
452+
// * custom rules for built-in types
453+
// * the type definition otherwise (rule `WellFormed-Type`)
454+
let clauses = match ty.sty {
455+
ty::Projection(data) => {
456+
self.infcx.tcx.program_clauses_for(data.item_def_id)
457+
}
458+
459+
// These types are always WF (recall that we do not check
460+
// for parameters to be WF)
461+
ty::Bool |
462+
ty::Char |
463+
ty::Int(..) |
464+
ty::Uint(..) |
465+
ty::Float(..) |
466+
ty::Str |
467+
ty::RawPtr(..) |
468+
ty::FnPtr(..) |
469+
ty::Param(..) |
470+
ty::Never => {
471+
ty::List::empty()
472+
}
473+
474+
// WF if inner type is `Sized`
475+
ty::Slice(..) |
476+
ty::Array(..) => {
477+
ty::List::empty()
478+
}
479+
480+
ty::Tuple(..) => {
481+
ty::List::empty()
482+
}
483+
484+
// WF if `sub_ty` outlives `region`
485+
ty::Ref(..) => {
486+
ty::List::empty()
487+
}
488+
489+
ty::Dynamic(..) => {
490+
// FIXME: no rules yet for trait objects
491+
ty::List::empty()
492+
}
493+
494+
ty::Adt(def, ..) => {
495+
self.infcx.tcx.program_clauses_for(def.did)
496+
}
497+
498+
ty::Foreign(def_id) |
499+
ty::FnDef(def_id, ..) |
500+
ty::Closure(def_id, ..) |
501+
ty::Generator(def_id, ..) |
502+
ty::Opaque(def_id, ..) => {
503+
self.infcx.tcx.program_clauses_for(def_id)
504+
}
505+
506+
ty::GeneratorWitness(..) |
507+
ty::UnnormalizedProjection(..) |
508+
ty::Infer(..) |
509+
ty::Error => {
510+
bug!("unexpected type {:?}", ty)
511+
}
512+
};
513+
514+
clauses.into_iter()
515+
.filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
516+
.cloned()
517+
.collect()
358518
}
359519

360-
DomainGoal::WellFormed(WellFormed::Trait(_trait_predicate)) => {
361-
// These come from -- the trait decl.
362-
panic!()
520+
DomainGoal::FromEnv(FromEnv::Trait(..)) => {
521+
// These come from:
522+
// * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
523+
// * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
524+
// * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
525+
// `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
526+
527+
// All of these rules are computed in the environment.
528+
vec![]
363529
}
364530

365-
DomainGoal::WellFormed(WellFormed::Ty(_ty)) => panic!(),
531+
DomainGoal::FromEnv(FromEnv::Ty(..)) => {
532+
// There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
533+
// comes from the environment).
534+
vec![]
535+
}
366536

367-
DomainGoal::FromEnv(FromEnv::Trait(_trait_predicate)) => panic!(),
537+
DomainGoal::Normalize(projection_predicate) => {
538+
// These come from -- assoc ty values (rule `Normalize-From-Impl`).
539+
let mut clauses = vec![];
368540

369-
DomainGoal::FromEnv(FromEnv::Ty(_ty)) => panic!(),
541+
assemble_clauses_from_assoc_ty_values(
542+
self.infcx.tcx,
543+
projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
544+
&mut clauses
545+
);
370546

371-
DomainGoal::Normalize(_) => panic!(),
372-
}
547+
clauses
548+
}
549+
};
550+
551+
let environment = self.infcx.tcx.lift_to_global(environment)
552+
.expect("environment is not global");
553+
clauses.extend(
554+
self.infcx.tcx.program_clauses_for_env(environment)
555+
.into_iter()
556+
.cloned()
557+
);
558+
clauses
373559
}
374560

375561
fn instantiate_binders_universally(

src/librustc_traits/lowering/environment.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,16 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
8686
ty::Slice(..) |
8787
ty::RawPtr(..) |
8888
ty::FnPtr(..) |
89-
ty::Never |
9089
ty::Tuple(..) |
90+
ty::Never |
91+
ty::Param(..) => (),
92+
9193
ty::GeneratorWitness(..) |
9294
ty::UnnormalizedProjection(..) |
93-
ty::Param(..) |
9495
ty::Infer(..) |
95-
ty::Error => (),
96+
ty::Error => {
97+
bug!("unexpected type {:?}", ty);
98+
}
9699
}
97100
}
98101

src/librustc_traits/lowering/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
433433
let wf_clause = ProgramClause {
434434
goal: DomainGoal::WellFormed(WellFormed::Ty(placeholder_ty)),
435435
hypotheses: tcx.mk_goals(iter::once(hypothesis)),
436-
category: ProgramClauseCategory::Other,
436+
category: ProgramClauseCategory::WellFormed,
437437
};
438438

439439
// Rule Implied-Trait-From-AssocTy

0 commit comments

Comments
 (0)