Auto merge of #87375 - fee1-dead:move-constness-to-traitpred, r=oli-obk
Try filtering out non-const impls when we expect const impls **TL;DR**: Associated types on const impls are now bounded; we now disallow calling a const function with bounds when the specified type param only has a non-const impl. r? `@oli-obk`
This commit is contained in:
commit
136eaa1b25
68 changed files with 517 additions and 211 deletions
|
@ -1340,7 +1340,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
|
||||
let bound_predicate = obligation.predicate.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::PredicateKind::Trait(pred, _) => {
|
||||
ty::PredicateKind::Trait(pred) => {
|
||||
let pred = bound_predicate.rebind(pred);
|
||||
associated_types.entry(span).or_default().extend(
|
||||
tcx.associated_items(pred.def_id())
|
||||
|
|
|
@ -606,16 +606,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut suggest_box = !obligations.is_empty();
|
||||
for o in obligations {
|
||||
match o.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(t, constness) => {
|
||||
let pred = ty::PredicateKind::Trait(
|
||||
ty::TraitPredicate {
|
||||
trait_ref: ty::TraitRef {
|
||||
def_id: t.def_id(),
|
||||
substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]),
|
||||
},
|
||||
ty::PredicateKind::Trait(t) => {
|
||||
let pred = ty::PredicateKind::Trait(ty::TraitPredicate {
|
||||
trait_ref: ty::TraitRef {
|
||||
def_id: t.def_id(),
|
||||
substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]),
|
||||
},
|
||||
constness,
|
||||
);
|
||||
constness: t.constness,
|
||||
});
|
||||
let obl = Obligation::new(
|
||||
o.cause.clone(),
|
||||
self.param_env,
|
||||
|
|
|
@ -587,9 +587,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
debug!("coerce_unsized resolve step: {:?}", obligation);
|
||||
let bound_predicate = obligation.predicate.kind();
|
||||
let trait_pred = match bound_predicate.skip_binder() {
|
||||
ty::PredicateKind::Trait(trait_pred, _)
|
||||
if traits.contains(&trait_pred.def_id()) =>
|
||||
{
|
||||
ty::PredicateKind::Trait(trait_pred) if traits.contains(&trait_pred.def_id()) => {
|
||||
if unsize_did == trait_pred.def_id() {
|
||||
let self_ty = trait_pred.self_ty();
|
||||
let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
|
||||
|
|
|
@ -1292,7 +1292,13 @@ pub fn check_type_bounds<'tcx>(
|
|||
};
|
||||
|
||||
tcx.infer_ctxt().enter(move |infcx| {
|
||||
let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
|
||||
let constness = impl_ty
|
||||
.container
|
||||
.impl_def_id()
|
||||
.map(|did| tcx.impl_constness(did))
|
||||
.unwrap_or(hir::Constness::NotConst);
|
||||
|
||||
let inh = Inherited::with_constness(infcx, impl_ty.def_id.expect_local(), constness);
|
||||
let infcx = &inh.infcx;
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
|
||||
|
@ -1334,7 +1340,9 @@ pub fn check_type_bounds<'tcx>(
|
|||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
|
||||
if let Err(ref errors) =
|
||||
inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness)
|
||||
{
|
||||
infcx.report_fulfillment_errors(errors, None, false);
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
|||
let predicate = predicate.kind();
|
||||
let p = p.kind();
|
||||
match (predicate.skip_binder(), p.skip_binder()) {
|
||||
(ty::PredicateKind::Trait(a, _), ty::PredicateKind::Trait(b, _)) => {
|
||||
(ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => {
|
||||
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
|
||||
}
|
||||
(ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
|
||||
|
|
|
@ -714,7 +714,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
pub(in super::super) fn select_all_obligations_or_error(&self) {
|
||||
debug!("select_all_obligations_or_error");
|
||||
if let Err(errors) = self.fulfillment_cx.borrow_mut().select_all_or_error(&self) {
|
||||
if let Err(errors) = self
|
||||
.fulfillment_cx
|
||||
.borrow_mut()
|
||||
.select_all_with_constness_or_error(&self, self.inh.constness)
|
||||
{
|
||||
self.report_fulfillment_errors(&errors, self.inh.body_id, false);
|
||||
}
|
||||
}
|
||||
|
@ -725,7 +729,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
fallback_has_occurred: bool,
|
||||
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
|
||||
) {
|
||||
let result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
|
||||
let result = self
|
||||
.fulfillment_cx
|
||||
.borrow_mut()
|
||||
.select_with_constness_where_possible(self, self.inh.constness);
|
||||
if let Err(mut errors) = result {
|
||||
mutate_fulfillment_errors(&mut errors);
|
||||
self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);
|
||||
|
@ -796,7 +803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
bound_predicate.rebind(data).required_poly_trait_ref(self.tcx),
|
||||
obligation,
|
||||
)),
|
||||
ty::PredicateKind::Trait(data, _) => {
|
||||
ty::PredicateKind::Trait(data) => {
|
||||
Some((bound_predicate.rebind(data).to_poly_trait_ref(), obligation))
|
||||
}
|
||||
ty::PredicateKind::Subtype(..) => None,
|
||||
|
|
|
@ -923,7 +923,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
continue;
|
||||
}
|
||||
|
||||
if let ty::PredicateKind::Trait(predicate, _) =
|
||||
if let ty::PredicateKind::Trait(predicate) =
|
||||
error.obligation.predicate.kind().skip_binder()
|
||||
{
|
||||
// Collect the argument position for all arguments that could have caused this
|
||||
|
@ -974,7 +974,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let hir::ExprKind::Path(qpath) = &path.kind {
|
||||
if let hir::QPath::Resolved(_, path) = &qpath {
|
||||
for error in errors {
|
||||
if let ty::PredicateKind::Trait(predicate, _) =
|
||||
if let ty::PredicateKind::Trait(predicate) =
|
||||
error.obligation.predicate.kind().skip_binder()
|
||||
{
|
||||
// If any of the type arguments in this path segment caused the
|
||||
|
|
|
@ -174,7 +174,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn default_constness_for_trait_bounds(&self) -> hir::Constness {
|
||||
self.tcx.hir().get(self.body_id).constness()
|
||||
self.tcx.hir().get(self.body_id).constness_for_typeck()
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(
|
||||
|
@ -194,7 +194,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
|||
predicates: tcx.arena.alloc_from_iter(
|
||||
self.param_env.caller_bounds().iter().filter_map(|predicate| {
|
||||
match predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(data, _) if data.self_ty().is_param(index) => {
|
||||
ty::PredicateKind::Trait(data) if data.self_ty().is_param(index) => {
|
||||
// HACK(eddyb) should get the original `Span`.
|
||||
let span = tcx.def_span(def_id);
|
||||
Some((predicate, span))
|
||||
|
|
|
@ -52,6 +52,9 @@ pub struct Inherited<'a, 'tcx> {
|
|||
pub(super) deferred_generator_interiors:
|
||||
RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
|
||||
|
||||
/// Reports whether this is in a const context.
|
||||
pub(super) constness: hir::Constness,
|
||||
|
||||
pub(super) body_id: Option<hir::BodyId>,
|
||||
}
|
||||
|
||||
|
@ -93,6 +96,16 @@ impl<'tcx> InheritedBuilder<'tcx> {
|
|||
|
||||
impl Inherited<'a, 'tcx> {
|
||||
pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
|
||||
let tcx = infcx.tcx;
|
||||
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
Self::with_constness(infcx, def_id, tcx.hir().get(item_id).constness_for_typeck())
|
||||
}
|
||||
|
||||
pub(super) fn with_constness(
|
||||
infcx: InferCtxt<'a, 'tcx>,
|
||||
def_id: LocalDefId,
|
||||
constness: hir::Constness,
|
||||
) -> Self {
|
||||
let tcx = infcx.tcx;
|
||||
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let body_id = tcx.hir().maybe_body_owned_by(item_id);
|
||||
|
@ -108,6 +121,7 @@ impl Inherited<'a, 'tcx> {
|
|||
deferred_call_resolutions: RefCell::new(Default::default()),
|
||||
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||
deferred_generator_interiors: RefCell::new(Vec::new()),
|
||||
constness,
|
||||
body_id,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -507,7 +507,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
|
||||
// We don't care about regions here.
|
||||
.filter_map(|obligation| match obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
|
||||
ty::PredicateKind::Trait(trait_pred) if trait_pred.def_id() == sized_def_id => {
|
||||
let span = iter::zip(&predicates.predicates, &predicates.spans)
|
||||
.find_map(
|
||||
|(p, span)| {
|
||||
|
|
|
@ -832,7 +832,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
|
||||
let bound_predicate = predicate.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::PredicateKind::Trait(trait_predicate, _) => {
|
||||
ty::PredicateKind::Trait(trait_predicate) => {
|
||||
match *trait_predicate.trait_ref.self_ty().kind() {
|
||||
ty::Param(p) if p == param_ty => {
|
||||
Some(bound_predicate.rebind(trait_predicate.trait_ref))
|
||||
|
|
|
@ -683,7 +683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut collect_type_param_suggestions =
|
||||
|self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
|
||||
// We don't care about regions here, so it's fine to skip the binder here.
|
||||
if let (ty::Param(_), ty::PredicateKind::Trait(p, _)) =
|
||||
if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
|
||||
(self_ty.kind(), parent_pred.kind().skip_binder())
|
||||
{
|
||||
if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
|
||||
|
@ -763,7 +763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
|
||||
Some((obligation, projection_ty.self_ty()))
|
||||
}
|
||||
ty::PredicateKind::Trait(poly_trait_ref, _) => {
|
||||
ty::PredicateKind::Trait(poly_trait_ref) => {
|
||||
let p = poly_trait_ref.trait_ref;
|
||||
let self_ty = p.self_ty();
|
||||
let path = p.print_only_trait_path();
|
||||
|
@ -1200,7 +1200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
match p.kind().skip_binder() {
|
||||
// Hide traits if they are present in predicates as they can be fixed without
|
||||
// having to implement them.
|
||||
ty::PredicateKind::Trait(t, _) => t.def_id() == info.def_id,
|
||||
ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
|
||||
ty::PredicateKind::Projection(p) => {
|
||||
p.projection_ty.item_def_id == info.def_id
|
||||
}
|
||||
|
|
|
@ -689,7 +689,7 @@ fn bounds_from_generic_predicates<'tcx>(
|
|||
debug!("predicate {:?}", predicate);
|
||||
let bound_predicate = predicate.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::PredicateKind::Trait(trait_predicate, _) => {
|
||||
ty::PredicateKind::Trait(trait_predicate) => {
|
||||
let entry = types.entry(trait_predicate.self_ty()).or_default();
|
||||
let def_id = trait_predicate.def_id();
|
||||
if Some(def_id) != tcx.lang_items().sized_trait() {
|
||||
|
|
|
@ -364,7 +364,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
|
|||
}
|
||||
|
||||
fn default_constness_for_trait_bounds(&self) -> hir::Constness {
|
||||
self.node().constness()
|
||||
self.node().constness_for_typeck()
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(
|
||||
|
@ -640,7 +640,7 @@ fn type_param_predicates(
|
|||
)
|
||||
.into_iter()
|
||||
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(data, _) => data.self_ty().is_param(index),
|
||||
ty::PredicateKind::Trait(data) => data.self_ty().is_param(index),
|
||||
_ => false,
|
||||
}),
|
||||
);
|
||||
|
@ -1198,7 +1198,7 @@ fn super_predicates_that_define_assoc_type(
|
|||
// which will, in turn, reach indirect supertraits.
|
||||
for &(pred, span) in superbounds {
|
||||
debug!("superbound: {:?}", pred);
|
||||
if let ty::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
|
||||
if let ty::PredicateKind::Trait(bound) = pred.kind().skip_binder() {
|
||||
tcx.at(span).super_predicates_of(bound.def_id());
|
||||
}
|
||||
}
|
||||
|
@ -2439,7 +2439,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
|||
.iter()
|
||||
.copied()
|
||||
.filter(|(pred, _)| match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(tr, _) => !is_assoc_item_ty(tr.self_ty()),
|
||||
ty::PredicateKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
|
||||
ty::PredicateKind::Projection(proj) => {
|
||||
!is_assoc_item_ty(proj.projection_ty.self_ty())
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ fn associated_type_bounds<'tcx>(
|
|||
|
||||
let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(tr, _) => tr.self_ty() == item_ty,
|
||||
ty::PredicateKind::Trait(tr) => tr.self_ty() == item_ty,
|
||||
ty::PredicateKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
|
||||
ty::PredicateKind::TypeOutlives(outlives) => outlives.0 == item_ty,
|
||||
_ => false,
|
||||
|
|
|
@ -366,7 +366,10 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
|
|||
_ if predicate.is_global() => (),
|
||||
// We allow specializing on explicitly marked traits with no associated
|
||||
// items.
|
||||
ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => {
|
||||
ty::PredicateKind::Trait(ty::TraitPredicate {
|
||||
trait_ref,
|
||||
constness: hir::Constness::NotConst,
|
||||
}) => {
|
||||
if !matches!(
|
||||
trait_predicate_kind(tcx, predicate),
|
||||
Some(TraitSpecializationKind::Marker)
|
||||
|
@ -376,7 +379,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
|
|||
span,
|
||||
&format!(
|
||||
"cannot specialize on trait `{}`",
|
||||
tcx.def_path_str(pred.def_id()),
|
||||
tcx.def_path_str(trait_ref.def_id),
|
||||
),
|
||||
)
|
||||
.emit()
|
||||
|
@ -394,10 +397,11 @@ fn trait_predicate_kind<'tcx>(
|
|||
predicate: ty::Predicate<'tcx>,
|
||||
) -> Option<TraitSpecializationKind> {
|
||||
match predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => {
|
||||
Some(tcx.trait_def(pred.def_id()).specialization_kind)
|
||||
}
|
||||
ty::PredicateKind::Trait(_, hir::Constness::Const)
|
||||
ty::PredicateKind::Trait(ty::TraitPredicate {
|
||||
trait_ref,
|
||||
constness: hir::Constness::NotConst,
|
||||
}) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
|
||||
ty::PredicateKind::Trait(_)
|
||||
| ty::PredicateKind::RegionOutlives(_)
|
||||
| ty::PredicateKind::TypeOutlives(_)
|
||||
| ty::PredicateKind::Projection(_)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue