Skip to content

Commit 543c860

Browse files
committed
Constify Fn* traits
1 parent 2783fc4 commit 543c860

22 files changed

+128
-532
lines changed

compiler/rustc_hir_typeck/src/upvar.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
529529
// process any deferred resolutions.
530530
let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
531531
for deferred_call_resolution in deferred_call_resolutions {
532-
deferred_call_resolution.resolve(self);
532+
deferred_call_resolution.resolve(&mut FnCtxt::new(
533+
self,
534+
self.param_env,
535+
closure_def_id,
536+
));
533537
}
534538
}
535539

compiler/rustc_trait_selection/src/traits/effects.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use rustc_hir::{self as hir, LangItem};
22
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
33
use rustc_infer::traits::{
4-
ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
4+
ImplDerivedHostCause, ImplSource, Obligation, ObligationCause, ObligationCauseCode,
5+
PredicateObligation,
56
};
67
use rustc_middle::span_bug;
78
use rustc_middle::traits::query::NoSolution;
@@ -303,6 +304,9 @@ fn evaluate_host_effect_from_builtin_impls<'tcx>(
303304
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
304305
match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
305306
Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
307+
Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
308+
evaluate_host_effect_for_fn_goal(selcx, obligation)
309+
}
306310
_ => Err(EvaluationFailure::NoSolution),
307311
}
308312
}
@@ -398,6 +402,54 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>(
398402
.collect())
399403
}
400404

405+
// NOTE: Keep this in sync with `extract_fn_def_from_const_callable` in the new solver.
406+
fn evaluate_host_effect_for_fn_goal<'tcx>(
407+
selcx: &mut SelectionContext<'_, 'tcx>,
408+
obligation: &HostEffectObligation<'tcx>,
409+
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
410+
let tcx = selcx.tcx();
411+
let self_ty = obligation.predicate.self_ty();
412+
413+
let (def, args) = match *self_ty.kind() {
414+
ty::FnDef(def, args) => (def, args),
415+
416+
// We may support function pointers at some point in the future
417+
ty::FnPtr(..) => return Err(EvaluationFailure::NoSolution),
418+
419+
// Coroutines could implement `[const] Fn`,
420+
// but they don't really need to right now.
421+
ty::Closure(..)
422+
| ty::CoroutineClosure(_, _)
423+
| ty::Coroutine(_, _)
424+
| ty::CoroutineWitness(_, _) => {
425+
return Err(EvaluationFailure::NoSolution);
426+
}
427+
428+
// Everything else needs explicit impls or cannot have an impl
429+
_ => return Err(EvaluationFailure::NoSolution),
430+
};
431+
432+
match tcx.constness(def) {
433+
hir::Constness::Const => Ok(tcx
434+
.const_conditions(def)
435+
.instantiate(tcx, args)
436+
.into_iter()
437+
.map(|(c, span)| {
438+
let code = ObligationCauseCode::WhereClause(def, span);
439+
let cause =
440+
ObligationCause::new(obligation.cause.span, obligation.cause.body_id, code);
441+
Obligation::new(
442+
tcx,
443+
cause,
444+
obligation.param_env,
445+
c.to_host_effect_clause(tcx, obligation.predicate.constness),
446+
)
447+
})
448+
.collect()),
449+
hir::Constness::NotConst => Err(EvaluationFailure::NoSolution),
450+
}
451+
}
452+
401453
fn evaluate_host_effect_from_selection_candidate<'tcx>(
402454
selcx: &mut SelectionContext<'_, 'tcx>,
403455
obligation: &HostEffectObligation<'tcx>,

library/core/src/ops/function.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ use crate::marker::Tuple;
7272
)]
7373
#[fundamental] // so that regex can rely that `&str: !FnMut`
7474
#[must_use = "closures are lazy and do nothing unless called"]
75-
// FIXME(const_trait_impl) #[const_trait]
75+
#[const_trait]
76+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
7677
pub trait Fn<Args: Tuple>: FnMut<Args> {
7778
/// Performs the call operation.
7879
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -159,7 +160,8 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
159160
)]
160161
#[fundamental] // so that regex can rely that `&str: !FnMut`
161162
#[must_use = "closures are lazy and do nothing unless called"]
162-
// FIXME(const_trait_impl) #[const_trait]
163+
#[const_trait]
164+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
163165
pub trait FnMut<Args: Tuple>: FnOnce<Args> {
164166
/// Performs the call operation.
165167
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -238,7 +240,8 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
238240
)]
239241
#[fundamental] // so that regex can rely that `&str: !FnMut`
240242
#[must_use = "closures are lazy and do nothing unless called"]
241-
// FIXME(const_trait_impl) #[const_trait]
243+
#[const_trait]
244+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
242245
pub trait FnOnce<Args: Tuple> {
243246
/// The returned type after the call operator is used.
244247
#[lang = "fn_once_output"]
@@ -254,29 +257,32 @@ mod impls {
254257
use crate::marker::Tuple;
255258

256259
#[stable(feature = "rust1", since = "1.0.0")]
257-
impl<A: Tuple, F: ?Sized> Fn<A> for &F
260+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
261+
impl<A: Tuple, F: ?Sized> const Fn<A> for &F
258262
where
259-
F: Fn<A>,
263+
F: ~const Fn<A>,
260264
{
261265
extern "rust-call" fn call(&self, args: A) -> F::Output {
262266
(**self).call(args)
263267
}
264268
}
265269

266270
#[stable(feature = "rust1", since = "1.0.0")]
267-
impl<A: Tuple, F: ?Sized> FnMut<A> for &F
271+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
272+
impl<A: Tuple, F: ?Sized> const FnMut<A> for &F
268273
where
269-
F: Fn<A>,
274+
F: ~const Fn<A>,
270275
{
271276
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
272277
(**self).call(args)
273278
}
274279
}
275280

276281
#[stable(feature = "rust1", since = "1.0.0")]
277-
impl<A: Tuple, F: ?Sized> FnOnce<A> for &F
282+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
283+
impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F
278284
where
279-
F: Fn<A>,
285+
F: ~const Fn<A>,
280286
{
281287
type Output = F::Output;
282288

@@ -286,19 +292,21 @@ mod impls {
286292
}
287293

288294
#[stable(feature = "rust1", since = "1.0.0")]
289-
impl<A: Tuple, F: ?Sized> FnMut<A> for &mut F
295+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
296+
impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F
290297
where
291-
F: FnMut<A>,
298+
F: ~const FnMut<A>,
292299
{
293300
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
294301
(*self).call_mut(args)
295302
}
296303
}
297304

298305
#[stable(feature = "rust1", since = "1.0.0")]
299-
impl<A: Tuple, F: ?Sized> FnOnce<A> for &mut F
306+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
307+
impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F
300308
where
301-
F: FnMut<A>,
309+
F: ~const FnMut<A>,
302310
{
303311
type Output = F::Output;
304312
extern "rust-call" fn call_once(self, args: A) -> F::Output {

tests/ui/consts/fn_trait_refs.stderr

Lines changed: 3 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -4,151 +4,6 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls`
44
LL | #![feature(const_fn_trait_ref_impls)]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^
66

7-
error: `[const]` can only be applied to `#[const_trait]` traits
8-
--> $DIR/fn_trait_refs.rs:14:8
9-
|
10-
LL | T: [const] Fn<()> + [const] Destruct,
11-
| ^^^^^^^ can't be applied to `Fn`
12-
|
13-
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
14-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
15-
16-
error: `[const]` can only be applied to `#[const_trait]` traits
17-
--> $DIR/fn_trait_refs.rs:14:8
18-
|
19-
LL | T: [const] Fn<()> + [const] Destruct,
20-
| ^^^^^^^ can't be applied to `Fn`
21-
|
22-
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
23-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
24-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25-
26-
error: `[const]` can only be applied to `#[const_trait]` traits
27-
--> $DIR/fn_trait_refs.rs:14:8
28-
|
29-
LL | T: [const] Fn<()> + [const] Destruct,
30-
| ^^^^^^^ can't be applied to `Fn`
31-
|
32-
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
33-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
34-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
35-
36-
error: `[const]` can only be applied to `#[const_trait]` traits
37-
--> $DIR/fn_trait_refs.rs:21:8
38-
|
39-
LL | T: [const] FnMut<()> + [const] Destruct,
40-
| ^^^^^^^ can't be applied to `FnMut`
41-
|
42-
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
43-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
44-
45-
error: `[const]` can only be applied to `#[const_trait]` traits
46-
--> $DIR/fn_trait_refs.rs:21:8
47-
|
48-
LL | T: [const] FnMut<()> + [const] Destruct,
49-
| ^^^^^^^ can't be applied to `FnMut`
50-
|
51-
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
52-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
53-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
54-
55-
error: `[const]` can only be applied to `#[const_trait]` traits
56-
--> $DIR/fn_trait_refs.rs:21:8
57-
|
58-
LL | T: [const] FnMut<()> + [const] Destruct,
59-
| ^^^^^^^ can't be applied to `FnMut`
60-
|
61-
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
62-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
63-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
64-
65-
error: `[const]` can only be applied to `#[const_trait]` traits
66-
--> $DIR/fn_trait_refs.rs:28:8
67-
|
68-
LL | T: [const] FnOnce<()>,
69-
| ^^^^^^^ can't be applied to `FnOnce`
70-
|
71-
note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
72-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
73-
74-
error: `[const]` can only be applied to `#[const_trait]` traits
75-
--> $DIR/fn_trait_refs.rs:28:8
76-
|
77-
LL | T: [const] FnOnce<()>,
78-
| ^^^^^^^ can't be applied to `FnOnce`
79-
|
80-
note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
81-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
82-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
83-
84-
error: `[const]` can only be applied to `#[const_trait]` traits
85-
--> $DIR/fn_trait_refs.rs:28:8
86-
|
87-
LL | T: [const] FnOnce<()>,
88-
| ^^^^^^^ can't be applied to `FnOnce`
89-
|
90-
note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
91-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
92-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
93-
94-
error: `[const]` can only be applied to `#[const_trait]` traits
95-
--> $DIR/fn_trait_refs.rs:35:8
96-
|
97-
LL | T: [const] Fn<()> + [const] Destruct,
98-
| ^^^^^^^ can't be applied to `Fn`
99-
|
100-
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
101-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
102-
103-
error: `[const]` can only be applied to `#[const_trait]` traits
104-
--> $DIR/fn_trait_refs.rs:35:8
105-
|
106-
LL | T: [const] Fn<()> + [const] Destruct,
107-
| ^^^^^^^ can't be applied to `Fn`
108-
|
109-
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
110-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
111-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
112-
113-
error: `[const]` can only be applied to `#[const_trait]` traits
114-
--> $DIR/fn_trait_refs.rs:35:8
115-
|
116-
LL | T: [const] Fn<()> + [const] Destruct,
117-
| ^^^^^^^ can't be applied to `Fn`
118-
|
119-
note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
120-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
121-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
122-
123-
error: `[const]` can only be applied to `#[const_trait]` traits
124-
--> $DIR/fn_trait_refs.rs:49:8
125-
|
126-
LL | T: [const] FnMut<()> + [const] Destruct,
127-
| ^^^^^^^ can't be applied to `FnMut`
128-
|
129-
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
130-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
131-
132-
error: `[const]` can only be applied to `#[const_trait]` traits
133-
--> $DIR/fn_trait_refs.rs:49:8
134-
|
135-
LL | T: [const] FnMut<()> + [const] Destruct,
136-
| ^^^^^^^ can't be applied to `FnMut`
137-
|
138-
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
139-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
140-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
141-
142-
error: `[const]` can only be applied to `#[const_trait]` traits
143-
--> $DIR/fn_trait_refs.rs:49:8
144-
|
145-
LL | T: [const] FnMut<()> + [const] Destruct,
146-
| ^^^^^^^ can't be applied to `FnMut`
147-
|
148-
note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
149-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
150-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
151-
1527
error[E0277]: the trait bound `(i32, i32, i32): const PartialEq` is not satisfied
1538
--> $DIR/fn_trait_refs.rs:71:17
1549
|
@@ -161,31 +16,7 @@ error[E0277]: the trait bound `(i32, i32): const PartialEq` is not satisfied
16116
LL | assert!(test_two == (2, 2));
16217
| ^^^^^^^^^^^^^^^^^^
16318

164-
error[E0015]: cannot call non-const closure in constant functions
165-
--> $DIR/fn_trait_refs.rs:16:5
166-
|
167-
LL | f()
168-
| ^^^
169-
|
170-
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
171-
172-
error[E0015]: cannot call non-const closure in constant functions
173-
--> $DIR/fn_trait_refs.rs:23:5
174-
|
175-
LL | f()
176-
| ^^^
177-
|
178-
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
179-
180-
error[E0015]: cannot call non-const closure in constant functions
181-
--> $DIR/fn_trait_refs.rs:30:5
182-
|
183-
LL | f()
184-
| ^^^
185-
|
186-
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
187-
188-
error: aborting due to 21 previous errors
19+
error: aborting due to 3 previous errors
18920

190-
Some errors have detailed explanations: E0015, E0277, E0635.
191-
For more information about an error, try `rustc --explain E0015`.
21+
Some errors have detailed explanations: E0277, E0635.
22+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)