about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-07-22 12:48:29 +0000
committerbors <bors@rust-lang.org>2022-07-22 12:48:29 +0000
commit22d25f21dc008785f52e7c2833de4f4236b1066b (patch)
treea0889b431c8ff50d97957efce13bde8f21d91649 /compiler
parent41419e70366962c9a878bfe673ef4df38db6f7f1 (diff)
parenta0ebb2ed8b59e8eec9add6acda0673dcf468596f (diff)
downloadrust-22d25f21dc008785f52e7c2833de4f4236b1066b.tar.gz
rust-22d25f21dc008785f52e7c2833de4f4236b1066b.zip
Auto merge of #99521 - fee1-dead-contrib:const_fix_hax, r=oli-obk
Fix hack that remaps env constness.

WARNING: might have perf implications.

Are there any more problems with having a constness in the `ParamEnv` now? :)

r? `@oli-obk`
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/relationships.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs73
-rw-r--r--compiler/rustc_typeck/src/check/closure.rs6
4 files changed, 45 insertions, 51 deletions
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 4346dbdb16b..281a1265546 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -575,6 +575,19 @@ impl<'tcx> Predicate<'tcx> {
 
         Some(tcx.mk_predicate(kind))
     }
+
+    pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self {
+        if let PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) = self.kind().skip_binder()
+            && constness != BoundConstness::NotConst
+        {
+            self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Trait(TraitPredicate {
+                trait_ref,
+                constness: BoundConstness::NotConst,
+                polarity,
+            })));
+        }
+        self
+    }
 }
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
index 56bdeafeeca..8148e2b7871 100644
--- a/compiler/rustc_trait_selection/src/traits/relationships.rs
+++ b/compiler/rustc_trait_selection/src/traits/relationships.rs
@@ -31,14 +31,14 @@ pub(crate) fn update<'tcx, T>(
             obligation
                 .predicate
                 .kind()
-                .map_bound(|_| {
+                .rebind(
                     // (*) binder moved here
                     ty::PredicateKind::Trait(ty::TraitPredicate {
                         trait_ref,
                         constness: tpred.constness,
                         polarity: tpred.polarity,
                     })
-                })
+                )
                 .to_predicate(infcx.tcx),
         );
         // Don't report overflow errors. Otherwise equivalent to may_hold.
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index da8ca6e5749..d4c9fd1c5f9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -42,115 +42,96 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &TraitObligation<'tcx>,
         candidate: SelectionCandidate<'tcx>,
     ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
-        let mut obligation = obligation;
-        let new_obligation;
-
-        // HACK(const_trait_impl): the surrounding environment is remapped to a non-const context
-        // because nested obligations might be actually `~const` then (incorrectly) requiring
-        // const impls. for example:
-        // ```
-        // pub trait Super {}
-        // pub trait Sub: Super {}
-        //
-        // impl<A> const Super for &A where A: ~const Super {}
-        // impl<A> const Sub for &A where A: ~const Sub {}
-        // ```
-        //
-        // The procedure to check the code above without the remapping code is as follows:
-        // ```
-        // CheckWf(impl const Sub for &A where A: ~const Sub) // <- const env
-        // CheckPredicate(&A: Super)
-        // CheckPredicate(A: ~const Super) // <- still const env, failure
-        // ```
-        if obligation.param_env.is_const() && !obligation.predicate.is_const_if_const() {
-            new_obligation = TraitObligation {
-                cause: obligation.cause.clone(),
-                param_env: obligation.param_env.without_const(),
-                ..*obligation
-            };
-            obligation = &new_obligation;
-        }
-
-        match candidate {
+        let mut impl_src = match candidate {
             BuiltinCandidate { has_nested } => {
                 let data = self.confirm_builtin_candidate(obligation, has_nested);
-                Ok(ImplSource::Builtin(data))
+                ImplSource::Builtin(data)
             }
 
             ParamCandidate(param) => {
                 let obligations =
                     self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
-                Ok(ImplSource::Param(obligations, param.skip_binder().constness))
+                ImplSource::Param(obligations, param.skip_binder().constness)
             }
 
             ImplCandidate(impl_def_id) => {
-                Ok(ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id)))
+                ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id))
             }
 
             AutoImplCandidate(trait_def_id) => {
                 let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
-                Ok(ImplSource::AutoImpl(data))
+                ImplSource::AutoImpl(data)
             }
 
             ProjectionCandidate(idx) => {
                 let obligations = self.confirm_projection_candidate(obligation, idx)?;
                 // FIXME(jschievink): constness
-                Ok(ImplSource::Param(obligations, ty::BoundConstness::NotConst))
+                ImplSource::Param(obligations, ty::BoundConstness::NotConst)
             }
 
             ObjectCandidate(idx) => {
                 let data = self.confirm_object_candidate(obligation, idx)?;
-                Ok(ImplSource::Object(data))
+                ImplSource::Object(data)
             }
 
             ClosureCandidate => {
                 let vtable_closure = self.confirm_closure_candidate(obligation)?;
-                Ok(ImplSource::Closure(vtable_closure))
+                ImplSource::Closure(vtable_closure)
             }
 
             GeneratorCandidate => {
                 let vtable_generator = self.confirm_generator_candidate(obligation)?;
-                Ok(ImplSource::Generator(vtable_generator))
+                ImplSource::Generator(vtable_generator)
             }
 
             FnPointerCandidate { .. } => {
                 let data = self.confirm_fn_pointer_candidate(obligation)?;
-                Ok(ImplSource::FnPointer(data))
+                ImplSource::FnPointer(data)
             }
 
             DiscriminantKindCandidate => {
-                Ok(ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData))
+                ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
             }
 
-            PointeeCandidate => Ok(ImplSource::Pointee(ImplSourcePointeeData)),
+            PointeeCandidate => ImplSource::Pointee(ImplSourcePointeeData),
 
             TraitAliasCandidate(alias_def_id) => {
                 let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
-                Ok(ImplSource::TraitAlias(data))
+                ImplSource::TraitAlias(data)
             }
 
             BuiltinObjectCandidate => {
                 // This indicates something like `Trait + Send: Send`. In this case, we know that
                 // this holds because that's what the object type is telling us, and there's really
                 // no additional obligations to prove and no types in particular to unify, etc.
-                Ok(ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst))
+                ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst)
             }
 
             BuiltinUnsizeCandidate => {
                 let data = self.confirm_builtin_unsize_candidate(obligation)?;
-                Ok(ImplSource::Builtin(data))
+                ImplSource::Builtin(data)
             }
 
             TraitUpcastingUnsizeCandidate(idx) => {
                 let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
-                Ok(ImplSource::TraitUpcasting(data))
+                ImplSource::TraitUpcasting(data)
             }
 
             ConstDestructCandidate(def_id) => {
                 let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
-                Ok(ImplSource::ConstDestruct(data))
+                ImplSource::ConstDestruct(data)
             }
+        };
+
+        if !obligation.predicate.is_const_if_const() {
+            // normalize nested predicates according to parent predicate's constness.
+            impl_src = impl_src.map(|mut o| {
+                o.predicate = o.predicate.without_const(self.tcx());
+                o
+            });
         }
+
+        Ok(impl_src)
     }
 
     fn confirm_projection_candidate(
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs
index 1681e6af812..2005fc24ed0 100644
--- a/compiler/rustc_typeck/src/check/closure.rs
+++ b/compiler/rustc_typeck/src/check/closure.rs
@@ -182,9 +182,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ty::PredicateKind::Projection(proj_predicate) => self
                             .deduce_sig_from_projection(
                                 Some(span.0),
-                                pred.0.kind().rebind(
-                                    pred.map_bound(|_| proj_predicate).subst(self.tcx, substs),
-                                ),
+                                pred.0
+                                    .kind()
+                                    .rebind(pred.rebind(proj_predicate).subst(self.tcx, substs)),
                             ),
                         _ => None,
                     });