about summary refs log tree commit diff
path: root/compiler/rustc_next_trait_solver/src
diff options
context:
space:
mode:
authorRémy Rakic <remy.rakic+github@gmail.com>2025-01-17 17:00:59 +0000
committerRémy Rakic <remy.rakic+github@gmail.com>2025-01-17 18:50:29 +0000
commit00844be421ff67872681cf9c4d1a4cb8d4e90891 (patch)
treeb4a6ef7abd22caa26f979b3d8a987933d43a4fc0 /compiler/rustc_next_trait_solver/src
parent73c0ae6aec8f3d07467dfb9339761fa2eec92a44 (diff)
downloadrust-00844be421ff67872681cf9c4d1a4cb8d4e90891.tar.gz
rust-00844be421ff67872681cf9c4d1a4cb8d4e90891.zip
new solver: prefer trivial builtin impls over where-clauses
for now, only builtin `Sized` impls are tracked as being `Trivial`
Diffstat (limited to 'compiler/rustc_next_trait_solver/src')
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs28
1 files changed, 26 insertions, 2 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index f4d7c3ce76c..4faa243c02a 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -8,6 +8,7 @@ use rustc_type_ir::lang_items::TraitSolverLangItem;
 use rustc_type_ir::solve::CanonicalResponse;
 use rustc_type_ir::visit::TypeVisitableExt as _;
 use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate};
+use smallvec::SmallVec;
 use tracing::{instrument, trace};
 
 use crate::delegate::SolverDelegate;
@@ -225,7 +226,7 @@ where
         }
 
         ecx.probe_and_evaluate_goal_for_constituent_tys(
-            CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
+            CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
             goal,
             structural_traits::instantiate_constituent_tys_for_sized_trait,
         )
@@ -1194,7 +1195,30 @@ where
             };
         }
 
-        // FIXME: prefer trivial builtin impls
+        // We prefer trivial builtin candidates, i.e. builtin impls without any
+        // nested requirements, over all others. This is a fix for #53123 and
+        // prevents where-bounds from accidentally extending the lifetime of a
+        // variable.
+        if candidates
+            .iter()
+            .any(|c| matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial)))
+        {
+            let trivial_builtin_impls: SmallVec<[_; 1]> = candidates
+                .iter()
+                .filter(|c| {
+                    matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
+                })
+                .map(|c| c.result)
+                .collect();
+            // There should only ever be a single trivial builtin candidate
+            // as they would otherwise overlap.
+            assert_eq!(trivial_builtin_impls.len(), 1);
+            return if let Some(response) = self.try_merge_responses(&trivial_builtin_impls) {
+                Ok((response, Some(TraitGoalProvenVia::Misc)))
+            } else {
+                Ok((self.bail_with_ambiguity(&trivial_builtin_impls), None))
+            };
+        }
 
         // If there are non-global where-bounds, prefer where-bounds
         // (including global ones) over everything else.