about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/traits
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-02-21 18:27:17 +0000
committerMichael Goulet <michael@errs.io>2023-02-23 02:12:51 +0000
commit9bf32c40b4c1b7558aee3421ed3e8e73ef518dd9 (patch)
treec41aba5c5a5e475749366249a8f8820364411a3d /compiler/rustc_trait_selection/src/traits
parent02b3664766f1053746a3068c6eed6c464d8a40dc (diff)
downloadrust-9bf32c40b4c1b7558aee3421ed3e8e73ef518dd9.tar.gz
rust-9bf32c40b4c1b7558aee3421ed3e8e73ef518dd9.zip
Don't project specializable RPITIT projection
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs27
1 files changed, 22 insertions, 5 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 279725b16d8..c9e46ba41b0 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1307,21 +1307,38 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
         let _ = selcx.infcx.commit_if_ok(|_| {
             match selcx.select(&obligation.with(tcx, trait_predicate)) {
                 Ok(Some(super::ImplSource::UserDefined(data))) => {
-                    candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
-                    Ok(())
+                    let Ok(leaf_def) = specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) else {
+                        return Err(());
+                    };
+                    // Only reveal a specializable default if we're past type-checking
+                    // and the obligation is monomorphic, otherwise passes such as
+                    // transmute checking and polymorphic MIR optimizations could
+                    // get a result which isn't correct for all monomorphizations.
+                    if leaf_def.is_final()
+                        || (obligation.param_env.reveal() == Reveal::All
+                            && !selcx
+                                .infcx
+                                .resolve_vars_if_possible(obligation.predicate.trait_ref(tcx))
+                                .still_further_specializable())
+                    {
+                        candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
+                        Ok(())
+                    } else {
+                        Err(())
+                    }
                 }
                 Ok(None) => {
                     candidate_set.mark_ambiguous();
-                    return Err(());
+                    Err(())
                 }
                 Ok(Some(_)) => {
                     // Don't know enough about the impl to provide a useful signature
-                    return Err(());
+                    Err(())
                 }
                 Err(e) => {
                     debug!(error = ?e, "selection error");
                     candidate_set.mark_error(e);
-                    return Err(());
+                    Err(())
                 }
             }
         });