Skip to content

Commit acb6a06

Browse files
committed
Fix various Chalk lowering bugs
- Add more well-known traits - Use the correct binders when lowering trait objects - Use correct substs when lowering trait objects - Use the correct binders for opaque_ty_data - Lower negative impls with the correct polarity - Supply associated type values - Use `predicates_defined_on` for where clauses
1 parent 299a65f commit acb6a06

File tree

4 files changed

+161
-42
lines changed

4 files changed

+161
-42
lines changed

compiler/rustc_traits/src/chalk/db.rs

+94-36
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl<'tcx> RustIrDatabase<'tcx> {
3737
def_id: DefId,
3838
bound_vars: SubstsRef<'tcx>,
3939
) -> Vec<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> {
40-
let predicates = self.interner.tcx.predicates_of(def_id).predicates;
40+
let predicates = self.interner.tcx.predicates_defined_on(def_id).predicates;
4141
let mut regions_substitutor =
4242
lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder);
4343
predicates
@@ -118,34 +118,27 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
118118
.map(|i| chalk_ir::AssocTypeId(i.def_id))
119119
.collect();
120120

121-
let well_known = if self.interner.tcx.lang_items().sized_trait() == Some(def_id) {
121+
let lang_items = self.interner.tcx.lang_items();
122+
let well_known = if lang_items.sized_trait() == Some(def_id) {
122123
Some(chalk_solve::rust_ir::WellKnownTrait::Sized)
123-
} else if self.interner.tcx.lang_items().copy_trait() == Some(def_id) {
124+
} else if lang_items.copy_trait() == Some(def_id) {
124125
Some(chalk_solve::rust_ir::WellKnownTrait::Copy)
125-
} else if self.interner.tcx.lang_items().clone_trait() == Some(def_id) {
126+
} else if lang_items.clone_trait() == Some(def_id) {
126127
Some(chalk_solve::rust_ir::WellKnownTrait::Clone)
127-
} else if self.interner.tcx.lang_items().drop_trait() == Some(def_id) {
128+
} else if lang_items.drop_trait() == Some(def_id) {
128129
Some(chalk_solve::rust_ir::WellKnownTrait::Drop)
129-
} else if self.interner.tcx.lang_items().fn_trait() == Some(def_id) {
130+
} else if lang_items.fn_trait() == Some(def_id) {
130131
Some(chalk_solve::rust_ir::WellKnownTrait::Fn)
131-
} else if self
132-
.interner
133-
.tcx
134-
.lang_items()
135-
.fn_once_trait()
136-
.map(|t| def_id == t)
137-
.unwrap_or(false)
138-
{
132+
} else if lang_items.fn_once_trait() == Some(def_id) {
139133
Some(chalk_solve::rust_ir::WellKnownTrait::FnOnce)
140-
} else if self
141-
.interner
142-
.tcx
143-
.lang_items()
144-
.fn_mut_trait()
145-
.map(|t| def_id == t)
146-
.unwrap_or(false)
147-
{
134+
} else if lang_items.fn_mut_trait() == Some(def_id) {
148135
Some(chalk_solve::rust_ir::WellKnownTrait::FnMut)
136+
} else if lang_items.unsize_trait() == Some(def_id) {
137+
Some(chalk_solve::rust_ir::WellKnownTrait::Unsize)
138+
} else if lang_items.unpin_trait() == Some(def_id) {
139+
Some(chalk_solve::rust_ir::WellKnownTrait::Unpin)
140+
} else if lang_items.coerce_unsized_trait() == Some(def_id) {
141+
Some(chalk_solve::rust_ir::WellKnownTrait::CoerceUnsized)
149142
} else {
150143
None
151144
};
@@ -281,11 +274,20 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
281274
where_clauses,
282275
};
283276

277+
let associated_ty_value_ids: Vec<_> = self
278+
.interner
279+
.tcx
280+
.associated_items(def_id)
281+
.in_definition_order()
282+
.filter(|i| i.kind == AssocKind::Type)
283+
.map(|i| chalk_solve::rust_ir::AssociatedTyValueId(i.def_id))
284+
.collect();
285+
284286
Arc::new(chalk_solve::rust_ir::ImplDatum {
285-
polarity: chalk_solve::rust_ir::Polarity::Positive,
287+
polarity: self.interner.tcx.impl_polarity(def_id).lower_into(&self.interner),
286288
binders: chalk_ir::Binders::new(binders, value),
287289
impl_type: chalk_solve::rust_ir::ImplType::Local,
288-
associated_ty_value_ids: vec![],
290+
associated_ty_value_ids,
289291
})
290292
}
291293

@@ -406,24 +408,38 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
406408
) -> Arc<chalk_solve::rust_ir::AssociatedTyValue<RustInterner<'tcx>>> {
407409
let def_id = associated_ty_id.0;
408410
let assoc_item = self.interner.tcx.associated_item(def_id);
409-
let impl_id = match assoc_item.container {
410-
AssocItemContainer::TraitContainer(def_id) => def_id,
411-
_ => unimplemented!("Not possible??"),
411+
let (impl_id, trait_id) = match assoc_item.container {
412+
AssocItemContainer::TraitContainer(def_id) => (def_id, def_id),
413+
AssocItemContainer::ImplContainer(def_id) => {
414+
(def_id, self.interner.tcx.impl_trait_ref(def_id).unwrap().def_id)
415+
}
412416
};
413417
match assoc_item.kind {
414418
AssocKind::Type => {}
415419
_ => unimplemented!("Not possible??"),
416420
}
421+
422+
let trait_item = self
423+
.interner
424+
.tcx
425+
.associated_items(trait_id)
426+
.find_by_name_and_kind(self.interner.tcx, assoc_item.ident, assoc_item.kind, trait_id)
427+
.unwrap();
417428
let bound_vars = bound_vars_for_item(self.interner.tcx, def_id);
418429
let binders = binders_for(&self.interner, bound_vars);
419-
let ty = self.interner.tcx.type_of(def_id);
430+
let ty = self
431+
.interner
432+
.tcx
433+
.type_of(def_id)
434+
.subst(self.interner.tcx, bound_vars)
435+
.lower_into(&self.interner);
420436

421437
Arc::new(chalk_solve::rust_ir::AssociatedTyValue {
422438
impl_id: chalk_ir::ImplId(impl_id),
423-
associated_ty_id: chalk_ir::AssocTypeId(def_id),
439+
associated_ty_id: chalk_ir::AssocTypeId(trait_item.def_id),
424440
value: chalk_ir::Binders::new(
425441
binders,
426-
chalk_solve::rust_ir::AssociatedTyValueBound { ty: ty.lower_into(&self.interner) },
442+
chalk_solve::rust_ir::AssociatedTyValueBound { ty },
427443
),
428444
})
429445
}
@@ -443,19 +459,61 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
443459
&self,
444460
opaque_ty_id: chalk_ir::OpaqueTyId<RustInterner<'tcx>>,
445461
) -> Arc<chalk_solve::rust_ir::OpaqueTyDatum<RustInterner<'tcx>>> {
446-
let bound_vars = bound_vars_for_item(self.interner.tcx, opaque_ty_id.0);
447-
let binders = binders_for(&self.interner, bound_vars);
462+
let bound_vars = ty::fold::shift_vars(
463+
self.interner.tcx,
464+
&bound_vars_for_item(self.interner.tcx, opaque_ty_id.0),
465+
1,
466+
);
448467
let where_clauses = self.where_clauses_for(opaque_ty_id.0, bound_vars);
449-
let bounds = self.bounds_for(opaque_ty_id.0, bound_vars);
468+
469+
let identity_substs = InternalSubsts::identity_for_item(self.interner.tcx, opaque_ty_id.0);
470+
471+
let bounds =
472+
self.interner
473+
.tcx
474+
.explicit_item_bounds(opaque_ty_id.0)
475+
.iter()
476+
.map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars))
477+
.map(|bound| {
478+
bound.fold_with(&mut ty::fold::BottomUpFolder {
479+
tcx: self.interner.tcx,
480+
ty_op: |ty| {
481+
if let ty::Opaque(def_id, substs) = *ty.kind() {
482+
if def_id == opaque_ty_id.0 && substs == identity_substs {
483+
return self.interner.tcx.mk_ty(ty::Bound(
484+
ty::INNERMOST,
485+
ty::BoundTy::from(ty::BoundVar::from_u32(0)),
486+
));
487+
}
488+
}
489+
ty
490+
},
491+
lt_op: |lt| lt,
492+
ct_op: |ct| ct,
493+
})
494+
})
495+
.filter_map(|bound| {
496+
LowerInto::<
497+
Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>
498+
>::lower_into(bound, &self.interner)
499+
})
500+
.collect();
501+
502+
// Binder for the bound variable representing the concrete impl Trait type.
503+
let existential_binder = chalk_ir::VariableKinds::from1(
504+
&self.interner,
505+
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
506+
);
450507

451508
let value = chalk_solve::rust_ir::OpaqueTyDatumBound {
452-
bounds: chalk_ir::Binders::new(binders.clone(), bounds),
453-
where_clauses: chalk_ir::Binders::new(binders, where_clauses),
509+
bounds: chalk_ir::Binders::new(existential_binder.clone(), bounds),
510+
where_clauses: chalk_ir::Binders::new(existential_binder, where_clauses),
454511
};
455512

513+
let binders = binders_for(&self.interner, bound_vars);
456514
Arc::new(chalk_solve::rust_ir::OpaqueTyDatum {
457515
opaque_ty_id,
458-
bound: chalk_ir::Binders::empty(&self.interner, value),
516+
bound: chalk_ir::Binders::new(binders, value),
459517
})
460518
}
461519

compiler/rustc_traits/src/chalk/lowering.rs

+34-6
Original file line numberDiff line numberDiff line change
@@ -638,8 +638,16 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
638638
self,
639639
interner: &RustInterner<'tcx>,
640640
) -> chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<RustInterner<'tcx>>> {
641+
// `Self` has one binder:
642+
// Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
643+
// The return type has two:
644+
// Binders<&[Binders<WhereClause<I>>]>
645+
// This means that any variables that are escaping `self` need to be
646+
// shifted in by one so that they are still escaping.
647+
let shifted_predicates = ty::fold::shift_vars(interner.tcx, &self, 1);
648+
641649
let (predicates, binders, _named_regions) =
642-
collect_bound_vars(interner, interner.tcx, &self);
650+
collect_bound_vars(interner, interner.tcx, &shifted_predicates);
643651
let self_ty = interner.tcx.mk_ty(ty::Bound(
644652
// This is going to be wrapped in a binder
645653
ty::DebruijnIndex::from_usize(1),
@@ -648,7 +656,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
648656
let where_clauses = predicates.into_iter().map(|predicate| match predicate {
649657
ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { def_id, substs }) => {
650658
chalk_ir::Binders::new(
651-
chalk_ir::VariableKinds::empty(interner),
659+
binders.clone(),
652660
chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef {
653661
trait_id: chalk_ir::TraitId(def_id),
654662
substitution: interner
@@ -659,25 +667,34 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
659667
)
660668
}
661669
ty::ExistentialPredicate::Projection(predicate) => chalk_ir::Binders::new(
662-
chalk_ir::VariableKinds::empty(interner),
670+
binders.clone(),
663671
chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
664672
alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
665673
associated_ty_id: chalk_ir::AssocTypeId(predicate.item_def_id),
666-
substitution: predicate.substs.lower_into(interner),
674+
substitution: interner
675+
.tcx
676+
.mk_substs_trait(self_ty, predicate.substs)
677+
.lower_into(interner),
667678
}),
668679
ty: predicate.ty.lower_into(interner),
669680
}),
670681
),
671682
ty::ExistentialPredicate::AutoTrait(def_id) => chalk_ir::Binders::new(
672-
chalk_ir::VariableKinds::empty(interner),
683+
binders.clone(),
673684
chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef {
674685
trait_id: chalk_ir::TraitId(def_id),
675686
substitution: interner.tcx.mk_substs_trait(self_ty, &[]).lower_into(interner),
676687
}),
677688
),
678689
});
690+
691+
// Binder for the bound variable representing the concrete underlying type.
692+
let existential_binder = chalk_ir::VariableKinds::from1(
693+
interner,
694+
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
695+
);
679696
let value = chalk_ir::QuantifiedWhereClauses::from_iter(interner, where_clauses);
680-
chalk_ir::Binders::new(binders, value)
697+
chalk_ir::Binders::new(existential_binder, value)
681698
}
682699
}
683700

@@ -750,6 +767,17 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound<RustInterner<'tcx>>>
750767
}
751768
}
752769

770+
impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::Polarity> for ty::ImplPolarity {
771+
fn lower_into(self, _interner: &RustInterner<'tcx>) -> chalk_solve::rust_ir::Polarity {
772+
match self {
773+
ty::ImplPolarity::Positive => chalk_solve::rust_ir::Polarity::Positive,
774+
ty::ImplPolarity::Negative => chalk_solve::rust_ir::Polarity::Negative,
775+
// FIXME(chalk) reservation impls
776+
ty::ImplPolarity::Reservation => chalk_solve::rust_ir::Polarity::Negative,
777+
}
778+
}
779+
}
780+
753781
impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>>>
754782
for ty::ProjectionPredicate<'tcx>
755783
{

src/test/ui/chalkify/arithmetic.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
// compile-flags: -Z chalk
3+
4+
fn main() {
5+
1 + 2;
6+
3 * 6;
7+
2 - 5;
8+
17 / 6;
9+
23 % 11;
10+
4 & 6;
11+
7 | 15;
12+
4 << 7;
13+
123 >> 3;
14+
1 == 2;
15+
5 != 5;
16+
6 < 2;
17+
7 > 11;
18+
3 <= 1;
19+
9 >= 14;
20+
}

src/test/ui/chalkify/trait-objects.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// check-pass
2+
// compile-flags: -Z chalk
3+
4+
use std::fmt::Display;
5+
6+
fn main() {
7+
let d: &dyn Display = &mut 3;
8+
// FIXME(chalk) should be able to call d.to_string() as well, but doing so
9+
// requires Chalk to be able to prove trait object well-formed goals.
10+
(&d).to_string();
11+
let f: &dyn Fn(i32) -> _ = &|x| x + x;
12+
f(2);
13+
}

0 commit comments

Comments
 (0)