diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 9fc39afac9f..3879d605292 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3261,8 +3261,13 @@ impl<'hir> Node<'hir> { } } - /// Returns `Constness::Const` when this node is a const fn/impl/item. - pub fn constness(&self) -> Constness { + /// Returns `Constness::Const` when this node is a const fn/impl/item, + /// + /// 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 { Node::Item(Item { kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), @@ -3280,6 +3285,7 @@ impl<'hir> Node<'hir> { Node::Item(Item { kind: ItemKind::Const(..), .. }) | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. }) + | Node::TraitItem(TraitItem { kind: TraitItemKind::Type(..), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const, _ => Constness::NotConst, diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index a2ffb30f43b..316a097556a 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1292,28 +1292,12 @@ pub fn check_type_bounds<'tcx>( }; 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 .container .impl_def_id() .map(|did| tcx.impl_constness(did)) .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 infcx = &inh.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) .iter() .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); 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); obligation.predicate = normalized_predicate; - inh.register_predicates(obligations.into_iter().map(|mut o| { - o.predicate = pred_map(o.predicate, tcx); - o - })); + inh.register_predicates(obligations); inh.register_predicate(obligation); } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index 75705e92e54..c0ecee155c6 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -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( diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 9d9c77ec072..6006c8f7513 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -98,7 +98,7 @@ 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()) + Self::with_constness(infcx, def_id, tcx.hir().get(item_id).constness_for_typeck()) } pub(super) fn with_constness( diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index c16b7bab3a3..9fbf5ab8533 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -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( diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index 8d72adb6b61..1dbd000afd7 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -1,5 +1,7 @@ // FIXME(fee1-dead): this should have a better error message #![feature(const_trait_impl)] +#![feature(const_trait_bound_opt_out)] +#![allow(incomplete_features)] struct NonConstAdd(i32); @@ -20,4 +22,12 @@ impl const Foo for NonConstAdd { //~^ ERROR } +trait Baz { + type Qux: ?const std::ops::Add; +} + +impl const Baz for NonConstAdd { + type Qux = NonConstAdd; // OK +} + fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr index 1fdc963e7b2..0cbeb71d235 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr @@ -1,5 +1,5 @@ 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; | ------------- required by this bound in `Foo::Bar`