Skip to content

Commit c9b21b0

Browse files
committed
orphan check: remove const generics fixme
1 parent 05e678c commit c9b21b0

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -746,8 +746,17 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
746746
result
747747
}
748748

749-
// FIXME: Constants should participate in orphan checking.
750749
fn visit_const(&mut self, _c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
750+
// All possible values for a constant parameter already exist
751+
// in the crate defining the trait, so they are always non-local.
752+
//
753+
// Because there's no way to have an impl where the first local
754+
// generic argument is a constant, we also don't have to fail
755+
// the orphan check when encountering a parameter or a generic constant.
756+
//
757+
// This means that we can completely ignore constants during the orphan check.
758+
//
759+
// See `src/test/ui/coherence/const-generics-orphan-check-ok.rs` for examples.
751760
ControlFlow::CONTINUE
752761
}
753762
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub trait Trait<const N: usize, T> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// check-pass
2+
// aux-build:trait-with-const-param.rs
3+
extern crate trait_with_const_param;
4+
use trait_with_const_param::*;
5+
6+
// Trivial case, const param after local type.
7+
struct Local1;
8+
impl<const N: usize, T> Trait<N, T> for Local1 {}
9+
10+
// Concrete consts behave the same as foreign types,
11+
// so this also trivially works.
12+
impl Trait<3, Local1> for i32 {}
13+
14+
// This case isn't as trivial as we would forbid type
15+
// parameters here, we do allow const parameters though.
16+
//
17+
// The reason that type parameters are forbidden for
18+
// `impl<T> Trait<T, LocalInA> for i32 {}` is that another
19+
// downstream crate can add `impl<T> Trait<LocalInB, T> for i32`.
20+
// As these two impls would overlap we forbid any impls which
21+
// have a type parameter in front of a local type.
22+
//
23+
// With const parameters this issue does not exist as there are no
24+
// constants local to another downstream crate.
25+
struct Local2;
26+
impl<const N: usize> Trait<N, Local2> for i32 {}
27+
28+
fn main() {}

0 commit comments

Comments
 (0)