Make assoc types work with ?const
opt=out
This commit is contained in:
parent
8c2a1e8e43
commit
1fa712d0ba
7 changed files with 24 additions and 27 deletions
|
@ -3261,8 +3261,13 @@ impl<'hir> Node<'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `Constness::Const` when this node is a const fn/impl/item.
|
/// Returns `Constness::Const` when this node is a const fn/impl/item,
|
||||||
pub fn constness(&self) -> Constness {
|
///
|
||||||
|
/// HACK(fee1-dead): or an associated type in a trait. This works because
|
||||||
|
/// only typeck cares about const trait predicates, so although the predicates
|
||||||
|
/// query would return const predicates when it does not need to be const,
|
||||||
|
/// it wouldn't have any effect.
|
||||||
|
pub fn constness_for_typeck(&self) -> Constness {
|
||||||
match self {
|
match self {
|
||||||
Node::Item(Item {
|
Node::Item(Item {
|
||||||
kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..),
|
kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..),
|
||||||
|
@ -3280,6 +3285,7 @@ impl<'hir> Node<'hir> {
|
||||||
|
|
||||||
Node::Item(Item { kind: ItemKind::Const(..), .. })
|
Node::Item(Item { kind: ItemKind::Const(..), .. })
|
||||||
| Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. })
|
| Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. })
|
||||||
|
| Node::TraitItem(TraitItem { kind: TraitItemKind::Type(..), .. })
|
||||||
| Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const,
|
| Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const,
|
||||||
|
|
||||||
_ => Constness::NotConst,
|
_ => Constness::NotConst,
|
||||||
|
|
|
@ -1292,28 +1292,12 @@ pub fn check_type_bounds<'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
tcx.infer_ctxt().enter(move |infcx| {
|
tcx.infer_ctxt().enter(move |infcx| {
|
||||||
// if the item is inside a const impl, we transform the predicates to be const.
|
|
||||||
let constness = impl_ty
|
let constness = impl_ty
|
||||||
.container
|
.container
|
||||||
.impl_def_id()
|
.impl_def_id()
|
||||||
.map(|did| tcx.impl_constness(did))
|
.map(|did| tcx.impl_constness(did))
|
||||||
.unwrap_or(hir::Constness::NotConst);
|
.unwrap_or(hir::Constness::NotConst);
|
||||||
|
|
||||||
let pred_map = match constness {
|
|
||||||
hir::Constness::NotConst => |p, _| p,
|
|
||||||
hir::Constness::Const => |p: ty::Predicate<'tcx>, tcx: TyCtxt<'tcx>| {
|
|
||||||
p.kind()
|
|
||||||
.map_bound(|kind| match kind {
|
|
||||||
ty::PredicateKind::Trait(mut tp) => {
|
|
||||||
tp.constness = hir::Constness::Const;
|
|
||||||
ty::PredicateKind::Trait(tp)
|
|
||||||
}
|
|
||||||
kind => kind,
|
|
||||||
})
|
|
||||||
.to_predicate(tcx)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let inh = Inherited::with_constness(infcx, impl_ty.def_id.expect_local(), constness);
|
let inh = Inherited::with_constness(infcx, impl_ty.def_id.expect_local(), constness);
|
||||||
let infcx = &inh.infcx;
|
let infcx = &inh.infcx;
|
||||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||||
|
@ -1332,7 +1316,7 @@ pub fn check_type_bounds<'tcx>(
|
||||||
.explicit_item_bounds(trait_ty.def_id)
|
.explicit_item_bounds(trait_ty.def_id)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(bound, span)| {
|
.map(|&(bound, span)| {
|
||||||
let concrete_ty_bound = pred_map(bound.subst(tcx, rebased_substs), tcx);
|
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
|
||||||
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
|
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
|
||||||
|
|
||||||
traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
|
traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
|
||||||
|
@ -1350,10 +1334,7 @@ pub fn check_type_bounds<'tcx>(
|
||||||
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
|
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
|
||||||
obligation.predicate = normalized_predicate;
|
obligation.predicate = normalized_predicate;
|
||||||
|
|
||||||
inh.register_predicates(obligations.into_iter().map(|mut o| {
|
inh.register_predicates(obligations);
|
||||||
o.predicate = pred_map(o.predicate, tcx);
|
|
||||||
o
|
|
||||||
}));
|
|
||||||
inh.register_predicate(obligation);
|
inh.register_predicate(obligation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_constness_for_trait_bounds(&self) -> hir::Constness {
|
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(
|
fn get_type_parameter_bounds(
|
||||||
|
|
|
@ -98,7 +98,7 @@ impl Inherited<'a, 'tcx> {
|
||||||
pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
|
pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
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())
|
Self::with_constness(infcx, def_id, tcx.hir().get(item_id).constness_for_typeck())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn with_constness(
|
pub(super) fn with_constness(
|
||||||
|
|
|
@ -364,7 +364,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_constness_for_trait_bounds(&self) -> hir::Constness {
|
fn default_constness_for_trait_bounds(&self) -> hir::Constness {
|
||||||
self.node().constness()
|
self.node().constness_for_typeck()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_type_parameter_bounds(
|
fn get_type_parameter_bounds(
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// FIXME(fee1-dead): this should have a better error message
|
// FIXME(fee1-dead): this should have a better error message
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
#![feature(const_trait_bound_opt_out)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
struct NonConstAdd(i32);
|
struct NonConstAdd(i32);
|
||||||
|
|
||||||
|
@ -20,4 +22,12 @@ impl const Foo for NonConstAdd {
|
||||||
//~^ ERROR
|
//~^ ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait Baz {
|
||||||
|
type Qux: ?const std::ops::Add;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl const Baz for NonConstAdd {
|
||||||
|
type Qux = NonConstAdd; // OK
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0277]: cannot add `NonConstAdd` to `NonConstAdd`
|
error[E0277]: cannot add `NonConstAdd` to `NonConstAdd`
|
||||||
--> $DIR/assoc-type.rs:19:5
|
--> $DIR/assoc-type.rs:21:5
|
||||||
|
|
|
|
||||||
LL | type Bar: std::ops::Add;
|
LL | type Bar: std::ops::Add;
|
||||||
| ------------- required by this bound in `Foo::Bar`
|
| ------------- required by this bound in `Foo::Bar`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue