@@ -42,115 +42,96 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
42
42
obligation: &TraitObligation<'tcx>,
43
43
candidate: SelectionCandidate<'tcx>,
44
44
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
45
- let mut obligation = obligation;
46
- let new_obligation;
47
-
48
- // HACK(const_trait_impl): the surrounding environment is remapped to a non-const context
49
- // because nested obligations might be actually `~const` then (incorrectly) requiring
50
- // const impls. for example:
51
- // ```
52
- // pub trait Super {}
53
- // pub trait Sub: Super {}
54
- //
55
- // impl<A> const Super for &A where A: ~const Super {}
56
- // impl<A> const Sub for &A where A: ~const Sub {}
57
- // ```
58
- //
59
- // The procedure to check the code above without the remapping code is as follows:
60
- // ```
61
- // CheckWf(impl const Sub for &A where A: ~const Sub) // <- const env
62
- // CheckPredicate(&A: Super)
63
- // CheckPredicate(A: ~const Super) // <- still const env, failure
64
- // ```
65
- if obligation.param_env.is_const() && !obligation.predicate.is_const_if_const() {
66
- new_obligation = TraitObligation {
67
- cause: obligation.cause.clone(),
68
- param_env: obligation.param_env.without_const(),
69
- ..*obligation
70
- };
71
- obligation = &new_obligation;
72
- }
73
-
74
- match candidate {
45
+ let mut impl_src = match candidate {
75
46
BuiltinCandidate { has_nested } => {
76
47
let data = self.confirm_builtin_candidate(obligation, has_nested);
77
- Ok( ImplSource::Builtin(data) )
48
+ ImplSource::Builtin(data)
78
49
}
79
50
80
51
ParamCandidate(param) => {
81
52
let obligations =
82
53
self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
83
- Ok( ImplSource::Param(obligations, param.skip_binder().constness) )
54
+ ImplSource::Param(obligations, param.skip_binder().constness)
84
55
}
85
56
86
57
ImplCandidate(impl_def_id) => {
87
- Ok( ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id) ))
58
+ ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id))
88
59
}
89
60
90
61
AutoImplCandidate(trait_def_id) => {
91
62
let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
92
- Ok( ImplSource::AutoImpl(data) )
63
+ ImplSource::AutoImpl(data)
93
64
}
94
65
95
66
ProjectionCandidate(idx) => {
96
67
let obligations = self.confirm_projection_candidate(obligation, idx)?;
97
68
// FIXME(jschievink): constness
98
- Ok( ImplSource::Param(obligations, ty::BoundConstness::NotConst) )
69
+ ImplSource::Param(obligations, ty::BoundConstness::NotConst)
99
70
}
100
71
101
72
ObjectCandidate(idx) => {
102
73
let data = self.confirm_object_candidate(obligation, idx)?;
103
- Ok( ImplSource::Object(data) )
74
+ ImplSource::Object(data)
104
75
}
105
76
106
77
ClosureCandidate => {
107
78
let vtable_closure = self.confirm_closure_candidate(obligation)?;
108
- Ok( ImplSource::Closure(vtable_closure) )
79
+ ImplSource::Closure(vtable_closure)
109
80
}
110
81
111
82
GeneratorCandidate => {
112
83
let vtable_generator = self.confirm_generator_candidate(obligation)?;
113
- Ok( ImplSource::Generator(vtable_generator) )
84
+ ImplSource::Generator(vtable_generator)
114
85
}
115
86
116
87
FnPointerCandidate { .. } => {
117
88
let data = self.confirm_fn_pointer_candidate(obligation)?;
118
- Ok( ImplSource::FnPointer(data) )
89
+ ImplSource::FnPointer(data)
119
90
}
120
91
121
92
DiscriminantKindCandidate => {
122
- Ok( ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) )
93
+ ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
123
94
}
124
95
125
- PointeeCandidate => Ok( ImplSource::Pointee(ImplSourcePointeeData) ),
96
+ PointeeCandidate => ImplSource::Pointee(ImplSourcePointeeData),
126
97
127
98
TraitAliasCandidate(alias_def_id) => {
128
99
let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
129
- Ok( ImplSource::TraitAlias(data) )
100
+ ImplSource::TraitAlias(data)
130
101
}
131
102
132
103
BuiltinObjectCandidate => {
133
104
// This indicates something like `Trait + Send: Send`. In this case, we know that
134
105
// this holds because that's what the object type is telling us, and there's really
135
106
// no additional obligations to prove and no types in particular to unify, etc.
136
- Ok( ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst) )
107
+ ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst)
137
108
}
138
109
139
110
BuiltinUnsizeCandidate => {
140
111
let data = self.confirm_builtin_unsize_candidate(obligation)?;
141
- Ok( ImplSource::Builtin(data) )
112
+ ImplSource::Builtin(data)
142
113
}
143
114
144
115
TraitUpcastingUnsizeCandidate(idx) => {
145
116
let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
146
- Ok( ImplSource::TraitUpcasting(data) )
117
+ ImplSource::TraitUpcasting(data)
147
118
}
148
119
149
120
ConstDestructCandidate(def_id) => {
150
121
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
151
- Ok( ImplSource::ConstDestruct(data) )
122
+ ImplSource::ConstDestruct(data)
152
123
}
124
+ };
125
+
126
+ if !obligation.predicate.is_const_if_const() {
127
+ // normalize nested predicates according to parent predicate's constness.
128
+ impl_src = impl_src.map(|mut o| {
129
+ o.predicate = o.predicate.without_const(self.tcx());
130
+ o
131
+ });
153
132
}
133
+
134
+ Ok(impl_src)
154
135
}
155
136
156
137
fn confirm_projection_candidate(
0 commit comments