diff --git a/Cargo.lock b/Cargo.lock index 940608975c5..d080a3f5b26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -255,7 +255,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" [[package]] name = "cargo" -version = "0.57.0" +version = "0.56.0" dependencies = [ "anyhow", "atty", @@ -388,7 +388,7 @@ dependencies = [ [[package]] name = "cargo-util" -version = "0.1.1" +version = "0.1.0" dependencies = [ "anyhow", "core-foundation", diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 2d177551664..994936351ff 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -16,6 +16,15 @@ pub enum AssocItemContainer { } impl AssocItemContainer { + /// Asserts that this is the `DefId` of an associated item declared + /// in an impl, and returns the trait `DefId`. + pub fn assert_impl(&self) -> DefId { + match *self { + ImplContainer(id) => id, + _ => bug!("associated item has wrong container type: {:?}", self), + } + } + /// Asserts that this is the `DefId` of an associated item declared /// in a trait, and returns the trait `DefId`. pub fn assert_trait(&self) -> DefId { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index d3586888155..01890f75026 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1292,7 +1292,24 @@ pub fn check_type_bounds<'tcx>( }; tcx.infer_ctxt().enter(move |infcx| { - let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); + // if the item is inside a const impl, we transform the predicates to be const. + let constness = tcx.impl_constness(impl_ty.container.assert_impl()); + 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); @@ -1310,7 +1327,7 @@ pub fn check_type_bounds<'tcx>( .explicit_item_bounds(trait_ty.def_id) .iter() .map(|&(bound, span)| { - let concrete_ty_bound = bound.subst(tcx, rebased_substs); + let concrete_ty_bound = pred_map(bound.subst(tcx, rebased_substs), tcx); debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound) @@ -1328,7 +1345,10 @@ pub fn check_type_bounds<'tcx>( debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); obligation.predicate = normalized_predicate; - inh.register_predicates(obligations); + inh.register_predicates(obligations.into_iter().map(|mut o| { + o.predicate = pred_map(o.predicate, tcx); + o + })); inh.register_predicate(obligation); } diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index fb7beae70ba..242edf5396c 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -52,6 +52,9 @@ pub struct Inherited<'a, 'tcx> { pub(super) deferred_generator_interiors: RefCell, hir::GeneratorKind)>>, + /// Reports whether this is in a const context. + pub(super) constness: hir::Constness, + pub(super) body_id: Option, } @@ -93,6 +96,12 @@ 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()) + } + + 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,12 +117,29 @@ 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, } } - pub(super) fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) { + #[instrument(level = "debug", skip(self))] + fn transform_predicate(&self, p: &mut ty::Predicate<'tcx>) { + // Don't transform non-const bounds into const bounds, + // but transform const bounds to non-const when we are + // not in a const context. + if let hir::Constness::NotConst = self.constness { + let kind = p.kind(); + if let ty::PredicateKind::Trait(pred) = kind.as_ref().skip_binder() { + let mut pred = *pred; + pred.constness = hir::Constness::NotConst; + *p = kind.rebind(ty::PredicateKind::Trait(pred)).to_predicate(self.tcx); + } + } + } + + pub(super) fn register_predicate(&self, mut obligation: traits::PredicateObligation<'tcx>) { debug!("register_predicate({:?})", obligation); + self.transform_predicate(&mut obligation.predicate); if obligation.has_escaping_bound_vars() { span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation); }