Skip to content

Commit d1b64f1

Browse files
Fix const specialization
1 parent 3644c4a commit d1b64f1

File tree

6 files changed

+13
-46
lines changed

6 files changed

+13
-46
lines changed

Diff for: compiler/rustc_hir_analysis/messages.ftl

-2
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ hir_analysis_const_param_ty_impl_on_unsized =
113113
the trait `ConstParamTy` may not be implemented for this type
114114
.label = type is not `Sized`
115115
116-
hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
117-
118116
hir_analysis_copy_impl_on_non_adt =
119117
the trait `Copy` cannot be implemented for this type
120118
.label = type is not a structure or enumeration

Diff for: compiler/rustc_hir_analysis/src/errors.rs

-7
Original file line numberDiff line numberDiff line change
@@ -1057,13 +1057,6 @@ pub(crate) struct EmptySpecialization {
10571057
pub base_impl_span: Span,
10581058
}
10591059

1060-
#[derive(Diagnostic)]
1061-
#[diag(hir_analysis_const_specialize)]
1062-
pub(crate) struct ConstSpecialize {
1063-
#[primary_span]
1064-
pub span: Span,
1065-
}
1066-
10671060
#[derive(Diagnostic)]
10681061
#[diag(hir_analysis_static_specialize)]
10691062
pub(crate) struct StaticSpecialize {

Diff for: compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

-26
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
//! on traits with methods can.
6767
6868
use rustc_data_structures::fx::FxHashSet;
69-
use rustc_hir as hir;
7069
use rustc_hir::def_id::{DefId, LocalDefId};
7170
use rustc_infer::infer::TyCtxtInferExt;
7271
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
@@ -134,7 +133,6 @@ fn check_always_applicable(
134133
unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args)
135134
};
136135

137-
res = res.and(check_constness(tcx, impl1_def_id, impl2_node, span));
138136
res = res.and(check_static_lifetimes(tcx, &parent_args, span));
139137
res = res.and(check_duplicate_params(tcx, impl1_args, parent_args, span));
140138
res = res.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span));
@@ -157,30 +155,6 @@ fn check_has_items(
157155
Ok(())
158156
}
159157

160-
/// Check that the specializing impl `impl1` is at least as const as the base
161-
/// impl `impl2`
162-
fn check_constness(
163-
tcx: TyCtxt<'_>,
164-
impl1_def_id: LocalDefId,
165-
impl2_node: Node,
166-
span: Span,
167-
) -> Result<(), ErrorGuaranteed> {
168-
if impl2_node.is_from_trait() {
169-
// This isn't a specialization
170-
return Ok(());
171-
}
172-
173-
let impl1_constness = tcx.constness(impl1_def_id.to_def_id());
174-
let impl2_constness = tcx.constness(impl2_node.def_id());
175-
176-
if let hir::Constness::Const = impl2_constness {
177-
if let hir::Constness::NotConst = impl1_constness {
178-
return Err(tcx.dcx().emit_err(errors::ConstSpecialize { span }));
179-
}
180-
}
181-
Ok(())
182-
}
183-
184158
/// Given a specializing impl `impl1`, and the base impl `impl2`, returns two
185159
/// generic parameters `(S1, S2)` that equate their trait references.
186160
/// The returned types are expressed in terms of the generics of `impl1`.

Diff for: compiler/rustc_trait_selection/src/traits/specialize/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,14 @@ pub(super) fn specializes(
339339
return false;
340340
}
341341

342-
// If the parent impl is const, then the specializing impl must be const.
342+
// If the parent impl is const, then the specializing impl must be const,
343+
// and it must not be *more restrictive* than the parent impl (that is,
344+
// it cannot be const in fewer cases than the parent impl).
343345
if tcx.is_conditionally_const(parent_impl_def_id) {
346+
if !tcx.is_conditionally_const(specializing_impl_def_id) {
347+
return false;
348+
}
349+
344350
let const_conditions = ocx.normalize(
345351
cause,
346352
param_env,

Diff for: tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Tests that specializing trait impls must be at least as const as the default impl.
2+
//@ revisions: spec min_spec
23

34
#![feature(const_trait_impl)]
4-
#![feature(min_specialization)]
5+
#![cfg_attr(spec, feature(specialization))]
6+
//[spec]~^ WARN the feature `specialization` is incomplete
7+
#![cfg_attr(min_spec, feature(min_specialization))]
58

69
#[const_trait]
710
trait Value {
@@ -16,7 +19,8 @@ impl<T> const Value for T {
1619

1720
struct FortyTwo;
1821

19-
impl Value for FortyTwo { //~ ERROR cannot specialize on const impl with non-const impl
22+
impl Value for FortyTwo {
23+
//~^ ERROR conflicting implementations
2024
fn value() -> u32 {
2125
println!("You can't do that (constly)");
2226
42

Diff for: tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr

-8
This file was deleted.

0 commit comments

Comments
 (0)