@@ -11,8 +11,9 @@ use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TyCtx
11
11
use rustc_infer:: traits:: solve:: Goal ;
12
12
use rustc_middle:: traits:: query:: NoSolution ;
13
13
use rustc_middle:: traits:: solve:: Certainty ;
14
- use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeFoldable , TypeVisitableExt as _, TypingMode } ;
15
- use rustc_next_trait_solver:: solve:: HasChanged ;
14
+ use rustc_middle:: ty:: {
15
+ self , Ty , TyCtxt , TypeFlags , TypeFoldable , TypeVisitableExt as _, TypingMode ,
16
+ } ;
16
17
use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span } ;
17
18
18
19
use crate :: traits:: { EvaluateConstErr , ObligationCause , specialization_graph} ;
@@ -61,19 +62,49 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
61
62
& self ,
62
63
goal : Goal < ' tcx , ty:: Predicate < ' tcx > > ,
63
64
span : Span ,
64
- ) -> Option < HasChanged > {
65
+ ) -> Option < Certainty > {
66
+ if let Some ( trait_pred) = goal. predicate . as_trait_clause ( ) {
67
+ if trait_pred. polarity ( ) == ty:: PredicatePolarity :: Positive {
68
+ match self . 0 . tcx . as_lang_item ( trait_pred. def_id ( ) ) {
69
+ Some ( LangItem :: Sized )
70
+ if self
71
+ . resolve_vars_if_possible ( trait_pred. self_ty ( ) . skip_binder ( ) )
72
+ . is_trivially_sized ( self . 0 . tcx ) =>
73
+ {
74
+ return Some ( Certainty :: Yes ) ;
75
+ }
76
+ Some ( LangItem :: Copy | LangItem :: Clone ) => {
77
+ let self_ty =
78
+ self . resolve_vars_if_possible ( trait_pred. self_ty ( ) . skip_binder ( ) ) ;
79
+ // Unlike `Sized` traits, which always prefer the built-in impl,
80
+ // `Copy`/`Clone` may be shadowed by a param-env candidate which
81
+ // could force a lifetime error or guide inference. While that's
82
+ // not generally desirable, it is observable, so for now let's
83
+ // ignore this fast path for types that have regions or infer.
84
+ if !self_ty
85
+ . has_type_flags ( TypeFlags :: HAS_FREE_REGIONS | TypeFlags :: HAS_INFER )
86
+ && self_ty. is_trivially_pure_clone_copy ( )
87
+ {
88
+ return Some ( Certainty :: Yes ) ;
89
+ }
90
+ }
91
+ _ => { }
92
+ }
93
+ }
94
+ }
95
+
65
96
let pred = goal. predicate . kind ( ) ;
66
97
match pred. no_bound_vars ( ) ? {
67
98
ty:: PredicateKind :: DynCompatible ( def_id) if self . 0 . tcx . is_dyn_compatible ( def_id) => {
68
- Some ( HasChanged :: No )
99
+ Some ( Certainty :: Yes )
69
100
}
70
101
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives ( outlives) ) => {
71
102
self . 0 . sub_regions (
72
103
SubregionOrigin :: RelateRegionParamBound ( span, None ) ,
73
104
outlives. 1 ,
74
105
outlives. 0 ,
75
106
) ;
76
- Some ( HasChanged :: No )
107
+ Some ( Certainty :: Yes )
77
108
}
78
109
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: TypeOutlives ( outlives) ) => {
79
110
self . 0 . register_type_outlives_constraint (
@@ -82,22 +113,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
82
113
& ObligationCause :: dummy_with_span ( span) ,
83
114
) ;
84
115
85
- Some ( HasChanged :: No )
86
- }
87
- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( trait_pred) ) => {
88
- match self . 0 . tcx . as_lang_item ( trait_pred. def_id ( ) ) {
89
- Some ( LangItem :: Sized )
90
- if trait_pred. self_ty ( ) . is_trivially_sized ( self . 0 . tcx ) =>
91
- {
92
- Some ( HasChanged :: No )
93
- }
94
- Some ( LangItem :: Copy | LangItem :: Clone )
95
- if trait_pred. self_ty ( ) . is_trivially_pure_clone_copy ( ) =>
96
- {
97
- Some ( HasChanged :: No )
98
- }
99
- _ => None ,
100
- }
116
+ Some ( Certainty :: Yes )
101
117
}
102
118
_ => None ,
103
119
}
0 commit comments