1
Fork 0

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
This commit is contained in:
Matthew Jasper 2020-10-28 20:04:39 +00:00
parent 299a65ff71
commit acb6a06123
4 changed files with 161 additions and 42 deletions

View file

@ -37,7 +37,7 @@ impl<'tcx> RustIrDatabase<'tcx> {
def_id: DefId,
bound_vars: SubstsRef<'tcx>,
) -> Vec<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> {
let predicates = self.interner.tcx.predicates_of(def_id).predicates;
let predicates = self.interner.tcx.predicates_defined_on(def_id).predicates;
let mut regions_substitutor =
lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder);
predicates
@ -118,34 +118,27 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
.map(|i| chalk_ir::AssocTypeId(i.def_id))
.collect();
let well_known = if self.interner.tcx.lang_items().sized_trait() == Some(def_id) {
let lang_items = self.interner.tcx.lang_items();
let well_known = if lang_items.sized_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Sized)
} else if self.interner.tcx.lang_items().copy_trait() == Some(def_id) {
} else if lang_items.copy_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Copy)
} else if self.interner.tcx.lang_items().clone_trait() == Some(def_id) {
} else if lang_items.clone_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Clone)
} else if self.interner.tcx.lang_items().drop_trait() == Some(def_id) {
} else if lang_items.drop_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Drop)
} else if self.interner.tcx.lang_items().fn_trait() == Some(def_id) {
} else if lang_items.fn_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Fn)
} else if self
.interner
.tcx
.lang_items()
.fn_once_trait()
.map(|t| def_id == t)
.unwrap_or(false)
{
} else if lang_items.fn_once_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::FnOnce)
} else if self
.interner
.tcx
.lang_items()
.fn_mut_trait()
.map(|t| def_id == t)
.unwrap_or(false)
{
} else if lang_items.fn_mut_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::FnMut)
} else if lang_items.unsize_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Unsize)
} else if lang_items.unpin_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::Unpin)
} else if lang_items.coerce_unsized_trait() == Some(def_id) {
Some(chalk_solve::rust_ir::WellKnownTrait::CoerceUnsized)
} else {
None
};
@ -281,11 +274,20 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
where_clauses,
};
let associated_ty_value_ids: Vec<_> = self
.interner
.tcx
.associated_items(def_id)
.in_definition_order()
.filter(|i| i.kind == AssocKind::Type)
.map(|i| chalk_solve::rust_ir::AssociatedTyValueId(i.def_id))
.collect();
Arc::new(chalk_solve::rust_ir::ImplDatum {
polarity: chalk_solve::rust_ir::Polarity::Positive,
polarity: self.interner.tcx.impl_polarity(def_id).lower_into(&self.interner),
binders: chalk_ir::Binders::new(binders, value),
impl_type: chalk_solve::rust_ir::ImplType::Local,
associated_ty_value_ids: vec![],
associated_ty_value_ids,
})
}
@ -406,24 +408,38 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
) -> Arc<chalk_solve::rust_ir::AssociatedTyValue<RustInterner<'tcx>>> {
let def_id = associated_ty_id.0;
let assoc_item = self.interner.tcx.associated_item(def_id);
let impl_id = match assoc_item.container {
AssocItemContainer::TraitContainer(def_id) => def_id,
_ => unimplemented!("Not possible??"),
let (impl_id, trait_id) = match assoc_item.container {
AssocItemContainer::TraitContainer(def_id) => (def_id, def_id),
AssocItemContainer::ImplContainer(def_id) => {
(def_id, self.interner.tcx.impl_trait_ref(def_id).unwrap().def_id)
}
};
match assoc_item.kind {
AssocKind::Type => {}
_ => unimplemented!("Not possible??"),
}
let trait_item = self
.interner
.tcx
.associated_items(trait_id)
.find_by_name_and_kind(self.interner.tcx, assoc_item.ident, assoc_item.kind, trait_id)
.unwrap();
let bound_vars = bound_vars_for_item(self.interner.tcx, def_id);
let binders = binders_for(&self.interner, bound_vars);
let ty = self.interner.tcx.type_of(def_id);
let ty = self
.interner
.tcx
.type_of(def_id)
.subst(self.interner.tcx, bound_vars)
.lower_into(&self.interner);
Arc::new(chalk_solve::rust_ir::AssociatedTyValue {
impl_id: chalk_ir::ImplId(impl_id),
associated_ty_id: chalk_ir::AssocTypeId(def_id),
associated_ty_id: chalk_ir::AssocTypeId(trait_item.def_id),
value: chalk_ir::Binders::new(
binders,
chalk_solve::rust_ir::AssociatedTyValueBound { ty: ty.lower_into(&self.interner) },
chalk_solve::rust_ir::AssociatedTyValueBound { ty },
),
})
}
@ -443,19 +459,61 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
&self,
opaque_ty_id: chalk_ir::OpaqueTyId<RustInterner<'tcx>>,
) -> Arc<chalk_solve::rust_ir::OpaqueTyDatum<RustInterner<'tcx>>> {
let bound_vars = bound_vars_for_item(self.interner.tcx, opaque_ty_id.0);
let binders = binders_for(&self.interner, bound_vars);
let bound_vars = ty::fold::shift_vars(
self.interner.tcx,
&bound_vars_for_item(self.interner.tcx, opaque_ty_id.0),
1,
);
let where_clauses = self.where_clauses_for(opaque_ty_id.0, bound_vars);
let bounds = self.bounds_for(opaque_ty_id.0, bound_vars);
let identity_substs = InternalSubsts::identity_for_item(self.interner.tcx, opaque_ty_id.0);
let bounds =
self.interner
.tcx
.explicit_item_bounds(opaque_ty_id.0)
.iter()
.map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars))
.map(|bound| {
bound.fold_with(&mut ty::fold::BottomUpFolder {
tcx: self.interner.tcx,
ty_op: |ty| {
if let ty::Opaque(def_id, substs) = *ty.kind() {
if def_id == opaque_ty_id.0 && substs == identity_substs {
return self.interner.tcx.mk_ty(ty::Bound(
ty::INNERMOST,
ty::BoundTy::from(ty::BoundVar::from_u32(0)),
));
}
}
ty
},
lt_op: |lt| lt,
ct_op: |ct| ct,
})
})
.filter_map(|bound| {
LowerInto::<
Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>
>::lower_into(bound, &self.interner)
})
.collect();
// Binder for the bound variable representing the concrete impl Trait type.
let existential_binder = chalk_ir::VariableKinds::from1(
&self.interner,
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
);
let value = chalk_solve::rust_ir::OpaqueTyDatumBound {
bounds: chalk_ir::Binders::new(binders.clone(), bounds),
where_clauses: chalk_ir::Binders::new(binders, where_clauses),
bounds: chalk_ir::Binders::new(existential_binder.clone(), bounds),
where_clauses: chalk_ir::Binders::new(existential_binder, where_clauses),
};
let binders = binders_for(&self.interner, bound_vars);
Arc::new(chalk_solve::rust_ir::OpaqueTyDatum {
opaque_ty_id,
bound: chalk_ir::Binders::empty(&self.interner, value),
bound: chalk_ir::Binders::new(binders, value),
})
}

View file

@ -638,8 +638,16 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
self,
interner: &RustInterner<'tcx>,
) -> chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<RustInterner<'tcx>>> {
// `Self` has one binder:
// Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
// The return type has two:
// Binders<&[Binders<WhereClause<I>>]>
// This means that any variables that are escaping `self` need to be
// shifted in by one so that they are still escaping.
let shifted_predicates = ty::fold::shift_vars(interner.tcx, &self, 1);
let (predicates, binders, _named_regions) =
collect_bound_vars(interner, interner.tcx, &self);
collect_bound_vars(interner, interner.tcx, &shifted_predicates);
let self_ty = interner.tcx.mk_ty(ty::Bound(
// This is going to be wrapped in a binder
ty::DebruijnIndex::from_usize(1),
@ -648,7 +656,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
let where_clauses = predicates.into_iter().map(|predicate| match predicate {
ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { def_id, substs }) => {
chalk_ir::Binders::new(
chalk_ir::VariableKinds::empty(interner),
binders.clone(),
chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef {
trait_id: chalk_ir::TraitId(def_id),
substitution: interner
@ -659,25 +667,34 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
)
}
ty::ExistentialPredicate::Projection(predicate) => chalk_ir::Binders::new(
chalk_ir::VariableKinds::empty(interner),
binders.clone(),
chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
associated_ty_id: chalk_ir::AssocTypeId(predicate.item_def_id),
substitution: predicate.substs.lower_into(interner),
substitution: interner
.tcx
.mk_substs_trait(self_ty, predicate.substs)
.lower_into(interner),
}),
ty: predicate.ty.lower_into(interner),
}),
),
ty::ExistentialPredicate::AutoTrait(def_id) => chalk_ir::Binders::new(
chalk_ir::VariableKinds::empty(interner),
binders.clone(),
chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef {
trait_id: chalk_ir::TraitId(def_id),
substitution: interner.tcx.mk_substs_trait(self_ty, &[]).lower_into(interner),
}),
),
});
// Binder for the bound variable representing the concrete underlying type.
let existential_binder = chalk_ir::VariableKinds::from1(
interner,
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
);
let value = chalk_ir::QuantifiedWhereClauses::from_iter(interner, where_clauses);
chalk_ir::Binders::new(binders, value)
chalk_ir::Binders::new(existential_binder, value)
}
}
@ -750,6 +767,17 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound<RustInterner<'tcx>>>
}
}
impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::Polarity> for ty::ImplPolarity {
fn lower_into(self, _interner: &RustInterner<'tcx>) -> chalk_solve::rust_ir::Polarity {
match self {
ty::ImplPolarity::Positive => chalk_solve::rust_ir::Polarity::Positive,
ty::ImplPolarity::Negative => chalk_solve::rust_ir::Polarity::Negative,
// FIXME(chalk) reservation impls
ty::ImplPolarity::Reservation => chalk_solve::rust_ir::Polarity::Negative,
}
}
}
impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>>>
for ty::ProjectionPredicate<'tcx>
{