Rollup merge of #99861 - lcnr:orphan-check-cg, r=jackh726
orphan check: rationalize our handling of constants cc `@rust-lang/types` `@rust-lang/project-const-generics` on whether you agree with this reasoning. r? types
This commit is contained in:
commit
92344e369b
3 changed files with 44 additions and 1 deletions
|
@ -734,7 +734,21 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Constants should participate in orphan checking.
|
/// All possible values for a constant parameter already exist
|
||||||
|
/// in the crate defining the trait, so they are always non-local[^1].
|
||||||
|
///
|
||||||
|
/// Because there's no way to have an impl where the first local
|
||||||
|
/// generic argument is a constant, we also don't have to fail
|
||||||
|
/// the orphan check when encountering a parameter or a generic constant.
|
||||||
|
///
|
||||||
|
/// This means that we can completely ignore constants during the orphan check.
|
||||||
|
///
|
||||||
|
/// See `src/test/ui/coherence/const-generics-orphan-check-ok.rs` for examples.
|
||||||
|
///
|
||||||
|
/// [^1]: This might not hold for function pointers or trait objects in the future.
|
||||||
|
/// As these should be quite rare as const arguments and especially rare as impl
|
||||||
|
/// parameters, allowing uncovered const parameters in impls seems more useful
|
||||||
|
/// than allowing `impl<T> Trait<local_fn_ptr, T> for i32` to compile.
|
||||||
fn visit_const(&mut self, _c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_const(&mut self, _c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
pub trait Trait<const N: usize, T> {}
|
28
src/test/ui/coherence/const-generics-orphan-check-ok.rs
Normal file
28
src/test/ui/coherence/const-generics-orphan-check-ok.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// check-pass
|
||||||
|
// aux-build:trait-with-const-param.rs
|
||||||
|
extern crate trait_with_const_param;
|
||||||
|
use trait_with_const_param::*;
|
||||||
|
|
||||||
|
// Trivial case, const param after local type.
|
||||||
|
struct Local1;
|
||||||
|
impl<const N: usize, T> Trait<N, T> for Local1 {}
|
||||||
|
|
||||||
|
// Concrete consts behave the same as foreign types,
|
||||||
|
// so this also trivially works.
|
||||||
|
impl Trait<3, Local1> for i32 {}
|
||||||
|
|
||||||
|
// This case isn't as trivial as we would forbid type
|
||||||
|
// parameters here, we do allow const parameters though.
|
||||||
|
//
|
||||||
|
// The reason that type parameters are forbidden for
|
||||||
|
// `impl<T> Trait<T, LocalInA> for i32 {}` is that another
|
||||||
|
// downstream crate can add `impl<T> Trait<LocalInB, T> for i32`.
|
||||||
|
// As these two impls would overlap we forbid any impls which
|
||||||
|
// have a type parameter in front of a local type.
|
||||||
|
//
|
||||||
|
// With const parameters this issue does not exist as there are no
|
||||||
|
// constants local to another downstream crate.
|
||||||
|
struct Local2;
|
||||||
|
impl<const N: usize> Trait<N, Local2> for i32 {}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Reference in a new issue