Skip to content

Commit 454955b

Browse files
authored
Unrolled build for rust-lang#134875
Rollup merge of rust-lang#134875 - compiler-errors:const-destruct-old-solver, r=lcnr Implement `const Destruct` in old solver Self-explanatory. Not totally settled that this is the best structure for built-in trait impls for effect goals in the new solver, but it's almost certainly the simplest. r? lcnr or re-roll
2 parents e26ff2f + c64f859 commit 454955b

15 files changed

+222
-133
lines changed

compiler/rustc_middle/src/ty/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1417,8 +1417,8 @@ impl Hash for FieldDef {
14171417
impl<'tcx> FieldDef {
14181418
/// Returns the type of this field. The resulting type is not normalized. The `arg` is
14191419
/// typically obtained via the second field of [`TyKind::Adt`].
1420-
pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> {
1421-
tcx.type_of(self.did).instantiate(tcx, arg)
1420+
pub fn ty(&self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
1421+
tcx.type_of(self.did).instantiate(tcx, args)
14221422
}
14231423

14241424
/// Computes the `Ident` of this variant by looking up the `Span`

compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs

+2
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,8 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
712712
}
713713
}
714714

715+
// NOTE: Keep this in sync with `evaluate_host_effect_for_destruct_goal` in
716+
// the old solver, for as long as that exists.
715717
pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
716718
cx: I,
717719
self_ty: I::Ty,

compiler/rustc_trait_selection/src/traits/effects.rs

+105-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_hir as hir;
1+
use rustc_hir::{self as hir, LangItem};
22
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
33
use rustc_infer::traits::{
44
ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
@@ -48,6 +48,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
4848
Err(EvaluationFailure::NoSolution) => {}
4949
}
5050

51+
match evaluate_host_effect_from_builtin_impls(selcx, obligation) {
52+
Ok(result) => return Ok(result),
53+
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
54+
Err(EvaluationFailure::NoSolution) => {}
55+
}
56+
5157
match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
5258
Ok(result) => return Ok(result),
5359
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
@@ -228,6 +234,104 @@ fn evaluate_host_effect_from_item_bounds<'tcx>(
228234
}
229235
}
230236

237+
fn evaluate_host_effect_from_builtin_impls<'tcx>(
238+
selcx: &mut SelectionContext<'_, 'tcx>,
239+
obligation: &HostEffectObligation<'tcx>,
240+
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
241+
match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
242+
Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
243+
_ => Err(EvaluationFailure::NoSolution),
244+
}
245+
}
246+
247+
// NOTE: Keep this in sync with `const_conditions_for_destruct` in the new solver.
248+
fn evaluate_host_effect_for_destruct_goal<'tcx>(
249+
selcx: &mut SelectionContext<'_, 'tcx>,
250+
obligation: &HostEffectObligation<'tcx>,
251+
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
252+
let tcx = selcx.tcx();
253+
let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, None);
254+
let self_ty = obligation.predicate.self_ty();
255+
256+
let const_conditions = match *self_ty.kind() {
257+
// An ADT is `~const Destruct` only if all of the fields are,
258+
// *and* if there is a `Drop` impl, that `Drop` impl is also `~const`.
259+
ty::Adt(adt_def, args) => {
260+
let mut const_conditions: ThinVec<_> = adt_def
261+
.all_fields()
262+
.map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
263+
.collect();
264+
match adt_def.destructor(tcx).map(|dtor| dtor.constness) {
265+
// `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`.
266+
Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
267+
// `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
268+
Some(hir::Constness::Const) => {
269+
let drop_def_id = tcx.require_lang_item(LangItem::Drop, None);
270+
let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]);
271+
const_conditions.push(drop_trait_ref);
272+
}
273+
// No `Drop` impl, no need to require anything else.
274+
None => {}
275+
}
276+
const_conditions
277+
}
278+
279+
ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
280+
thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [ty])]
281+
}
282+
283+
ty::Tuple(tys) => {
284+
tys.iter().map(|field_ty| ty::TraitRef::new(tcx, destruct_def_id, [field_ty])).collect()
285+
}
286+
287+
// Trivially implement `~const Destruct`
288+
ty::Bool
289+
| ty::Char
290+
| ty::Int(..)
291+
| ty::Uint(..)
292+
| ty::Float(..)
293+
| ty::Str
294+
| ty::RawPtr(..)
295+
| ty::Ref(..)
296+
| ty::FnDef(..)
297+
| ty::FnPtr(..)
298+
| ty::Never
299+
| ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
300+
| ty::Error(_) => thin_vec![],
301+
302+
// Coroutines and closures could implement `~const Drop`,
303+
// but they don't really need to right now.
304+
ty::Closure(_, _)
305+
| ty::CoroutineClosure(_, _)
306+
| ty::Coroutine(_, _)
307+
| ty::CoroutineWitness(_, _) => return Err(EvaluationFailure::NoSolution),
308+
309+
// FIXME(unsafe_binders): Unsafe binders could implement `~const Drop`
310+
// if their inner type implements it.
311+
ty::UnsafeBinder(_) => return Err(EvaluationFailure::NoSolution),
312+
313+
ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
314+
return Err(EvaluationFailure::NoSolution);
315+
}
316+
317+
ty::Bound(..)
318+
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
319+
panic!("unexpected type `{self_ty:?}`")
320+
}
321+
};
322+
323+
Ok(const_conditions
324+
.into_iter()
325+
.map(|trait_ref| {
326+
obligation.with(
327+
tcx,
328+
ty::Binder::dummy(trait_ref)
329+
.to_host_effect_clause(tcx, obligation.predicate.constness),
330+
)
331+
})
332+
.collect())
333+
}
334+
231335
fn evaluate_host_effect_from_selection_candiate<'tcx>(
232336
selcx: &mut SelectionContext<'_, 'tcx>,
233337
obligation: &HostEffectObligation<'tcx>,

tests/ui/consts/fn_trait_refs.stderr

+12-81
Original file line numberDiff line numberDiff line change
@@ -155,90 +155,21 @@ note: `FnMut` can't be used with `~const` because it isn't annotated with `#[con
155155
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
156156
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
157157

158-
error[E0277]: the trait bound `fn() -> i32 {one}: const Destruct` is not satisfied
159-
--> $DIR/fn_trait_refs.rs:70:32
158+
error[E0015]: cannot call non-const operator in constants
159+
--> $DIR/fn_trait_refs.rs:71:17
160160
|
161-
LL | let test_one = test_fn(one);
162-
| ------- ^^^
163-
| |
164-
| required by a bound introduced by this call
161+
LL | assert!(test_one == (1, 1, 1));
162+
| ^^^^^^^^^^^^^^^^^^^^^
165163
|
166-
note: required by a bound in `test_fn`
167-
--> $DIR/fn_trait_refs.rs:35:24
168-
|
169-
LL | const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output)
170-
| ------- required by a bound in this function
171-
LL | where
172-
LL | T: ~const Fn<()> + ~const Destruct,
173-
| ^^^^^^ required by this bound in `test_fn`
174-
175-
error[E0277]: the trait bound `fn() -> i32 {two}: const Destruct` is not satisfied
176-
--> $DIR/fn_trait_refs.rs:73:36
177-
|
178-
LL | let test_two = test_fn_mut(two);
179-
| ----------- ^^^
180-
| |
181-
| required by a bound introduced by this call
182-
|
183-
note: required by a bound in `test_fn_mut`
184-
--> $DIR/fn_trait_refs.rs:49:27
185-
|
186-
LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
187-
| ----------- required by a bound in this function
188-
LL | where
189-
LL | T: ~const FnMut<()> + ~const Destruct,
190-
| ^^^^^^ required by this bound in `test_fn_mut`
164+
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
191165

192-
error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
193-
--> $DIR/fn_trait_refs.rs:39:19
194-
|
195-
LL | tester_fn(&f),
196-
| --------- ^^
197-
| |
198-
| required by a bound introduced by this call
166+
error[E0015]: cannot call non-const operator in constants
167+
--> $DIR/fn_trait_refs.rs:74:17
199168
|
200-
note: required by a bound in `tester_fn`
201-
--> $DIR/fn_trait_refs.rs:14:24
169+
LL | assert!(test_two == (2, 2));
170+
| ^^^^^^^^^^^^^^^^^^
202171
|
203-
LL | const fn tester_fn<T>(f: T) -> T::Output
204-
| --------- required by a bound in this function
205-
LL | where
206-
LL | T: ~const Fn<()> + ~const Destruct,
207-
| ^^^^^^ required by this bound in `tester_fn`
208-
209-
error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
210-
--> $DIR/fn_trait_refs.rs:41:23
211-
|
212-
LL | tester_fn_mut(&f),
213-
| ------------- ^^
214-
| |
215-
| required by a bound introduced by this call
216-
|
217-
note: required by a bound in `tester_fn_mut`
218-
--> $DIR/fn_trait_refs.rs:21:27
219-
|
220-
LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
221-
| ------------- required by a bound in this function
222-
LL | where
223-
LL | T: ~const FnMut<()> + ~const Destruct,
224-
| ^^^^^^ required by this bound in `tester_fn_mut`
225-
226-
error[E0277]: the trait bound `&mut T: ~const Destruct` is not satisfied
227-
--> $DIR/fn_trait_refs.rs:53:23
228-
|
229-
LL | tester_fn_mut(&mut f),
230-
| ------------- ^^^^^^
231-
| |
232-
| required by a bound introduced by this call
233-
|
234-
note: required by a bound in `tester_fn_mut`
235-
--> $DIR/fn_trait_refs.rs:21:27
236-
|
237-
LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
238-
| ------------- required by a bound in this function
239-
LL | where
240-
LL | T: ~const FnMut<()> + ~const Destruct,
241-
| ^^^^^^ required by this bound in `tester_fn_mut`
172+
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
242173

243174
error[E0015]: cannot call non-const closure in constant functions
244175
--> $DIR/fn_trait_refs.rs:16:5
@@ -264,7 +195,7 @@ LL | f()
264195
|
265196
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
266197

267-
error: aborting due to 25 previous errors
198+
error: aborting due to 22 previous errors
268199

269-
Some errors have detailed explanations: E0015, E0277, E0635.
200+
Some errors have detailed explanations: E0015, E0635.
270201
For more information about an error, try `rustc --explain E0015`.

tests/ui/consts/promoted_const_call.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | let _: &'static _ = &id(&Panic);
55
| ^^^^^ - value is dropped here
66
| |
77
| the destructor for this type cannot be evaluated in constants
8+
|
9+
= note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
10+
= help: add `#![feature(const_destruct)]` to the crate attributes to enable
11+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
812

913
error[E0716]: temporary value dropped while borrowed
1014
--> $DIR/promoted_const_call.rs:16:26

tests/ui/impl-trait/normalize-tait-in-const.stderr

+2-17
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,6 @@ note: `Fn` can't be used with `~const` because it isn't annotated with `#[const_
1717
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
1818
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
1919

20-
error[E0277]: the trait bound `for<'a, 'b> fn(&'a foo::Alias<'b>) {foo}: const Destruct` is not satisfied
21-
--> $DIR/normalize-tait-in-const.rs:33:19
22-
|
23-
LL | with_positive(foo);
24-
| ------------- ^^^
25-
| |
26-
| required by a bound introduced by this call
27-
|
28-
note: required by a bound in `with_positive`
29-
--> $DIR/normalize-tait-in-const.rs:26:62
30-
|
31-
LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
32-
| ^^^^^^ required by this bound in `with_positive`
33-
3420
error[E0015]: cannot call non-const closure in constant functions
3521
--> $DIR/normalize-tait-in-const.rs:27:5
3622
|
@@ -39,7 +25,6 @@ LL | fun(filter_positive());
3925
|
4026
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
4127

42-
error: aborting due to 4 previous errors
28+
error: aborting due to 3 previous errors
4329

44-
Some errors have detailed explanations: E0015, E0277.
45-
For more information about an error, try `rustc --explain E0015`.
30+
For more information about this error, try `rustc --explain E0015`.

tests/ui/traits/const-traits/const-drop-bound.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
//@ known-bug: #110395
2-
// FIXME check-pass
1+
//@ check-pass
32

43
#![feature(const_trait_impl)]
54
#![feature(const_precise_live_drops, const_destruct)]

tests/ui/traits/const-traits/const-drop-bound.stderr

-17
This file was deleted.

tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
1+
error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
22
--> $DIR/const-drop-fail-2.rs:31:23
33
|
44
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7+
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
8+
--> $DIR/const-drop-fail-2.rs:25:25
9+
|
10+
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
11+
| ------ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
| |
13+
| unsatisfied trait bound introduced here
714
note: required by a bound in `check`
815
--> $DIR/const-drop-fail-2.rs:21:19
916
|

tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
1+
error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
22
--> $DIR/const-drop-fail-2.rs:31:23
33
|
44
LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7+
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
8+
--> $DIR/const-drop-fail-2.rs:25:25
9+
|
10+
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
11+
| ------ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
| |
13+
| unsatisfied trait bound introduced here
714
note: required by a bound in `check`
815
--> $DIR/const-drop-fail-2.rs:21:19
916
|

tests/ui/traits/const-traits/const-drop-fail.precise.stderr renamed to tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
2-
--> $DIR/const-drop-fail.rs:32:5
2+
--> $DIR/const-drop-fail.rs:33:5
33
|
44
LL | const _: () = check($exp);
55
| ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL | NonTrivialDrop,
88
| ^^^^^^^^^^^^^^
99
|
1010
note: required by a bound in `check`
11-
--> $DIR/const-drop-fail.rs:23:19
11+
--> $DIR/const-drop-fail.rs:24:19
1212
|
1313
LL | const fn check<T: ~const Destruct>(_: T) {}
1414
| ^^^^^^ required by this bound in `check`
1515

1616
error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
17-
--> $DIR/const-drop-fail.rs:34:5
17+
--> $DIR/const-drop-fail.rs:35:5
1818
|
1919
LL | const _: () = check($exp);
2020
| ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
2323
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424
|
2525
note: required by a bound in `check`
26-
--> $DIR/const-drop-fail.rs:23:19
26+
--> $DIR/const-drop-fail.rs:24:19
2727
|
2828
LL | const fn check<T: ~const Destruct>(_: T) {}
2929
| ^^^^^^ required by this bound in `check`

0 commit comments

Comments
 (0)