Fix calling function pointer const parameters. Also fixes inference of
function pointer const parameters.
This commit is contained in:
parent
ec557aa818
commit
2afd277bc3
@ -8,7 +8,7 @@
|
||||
use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::error::{ExpectedFound, TypeError};
|
||||
use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar};
|
||||
use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar, GlobalAlloc};
|
||||
use std::rc::Rc;
|
||||
use std::iter;
|
||||
use rustc_target::spec::abi;
|
||||
@ -561,37 +561,47 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||
// implement both `PartialEq` and `Eq`, corresponding to
|
||||
// `structural_match` types.
|
||||
// FIXME(const_generics): check for `structural_match` synthetic attribute.
|
||||
match (eagerly_eval(a), eagerly_eval(b)) {
|
||||
let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) {
|
||||
(ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => {
|
||||
// The caller should handle these cases!
|
||||
bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
|
||||
}
|
||||
(ConstValue::Param(a_p), ConstValue::Param(b_p)) if a_p.index == b_p.index => {
|
||||
Ok(a)
|
||||
return Ok(a);
|
||||
}
|
||||
(ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => {
|
||||
Ok(a)
|
||||
return Ok(a);
|
||||
}
|
||||
(a_val @ ConstValue::Scalar(Scalar::Raw { .. }), b_val @ _)
|
||||
if a.ty == b.ty && a_val == b_val =>
|
||||
{
|
||||
Ok(tcx.mk_const(ty::Const {
|
||||
val: a_val,
|
||||
ty: a.ty,
|
||||
}))
|
||||
(ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) if a.ty == b.ty => {
|
||||
if a_val == b_val {
|
||||
Ok(ConstValue::Scalar(a_val))
|
||||
} else if let ty::FnPtr(_) = a.ty.kind {
|
||||
let alloc_map = tcx.alloc_map.lock();
|
||||
let get_fn_instance = |val: Scalar| {
|
||||
let ptr = val.to_ptr().unwrap();
|
||||
if let Some(GlobalAlloc::Function(instance)) = alloc_map.get(ptr.alloc_id) {
|
||||
instance
|
||||
} else {
|
||||
bug!("Allocation for FnPtr isn't a function");
|
||||
}
|
||||
};
|
||||
let a_instance = get_fn_instance(a_val);
|
||||
let b_instance = get_fn_instance(b_val);
|
||||
if a_instance == b_instance {
|
||||
Ok(ConstValue::Scalar(a_val))
|
||||
} else {
|
||||
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
|
||||
}
|
||||
} else {
|
||||
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment
|
||||
// saying that we're not handling it intentionally.
|
||||
|
||||
(a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => {
|
||||
let a_bytes = get_slice_bytes(&tcx, a_val);
|
||||
let b_bytes = get_slice_bytes(&tcx, b_val);
|
||||
if a_bytes == b_bytes {
|
||||
Ok(tcx.mk_const(ty::Const {
|
||||
val: a_val,
|
||||
ty: a.ty,
|
||||
}))
|
||||
Ok(a_val)
|
||||
} else {
|
||||
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
|
||||
}
|
||||
@ -602,16 +612,16 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||
// FIXME(const_generics): this is wrong, as it is a projection
|
||||
(ConstValue::Unevaluated(a_def_id, a_substs),
|
||||
ConstValue::Unevaluated(b_def_id, b_substs)) if a_def_id == b_def_id => {
|
||||
let substs =
|
||||
relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
|
||||
Ok(tcx.mk_const(ty::Const {
|
||||
val: ConstValue::Unevaluated(a_def_id, &substs),
|
||||
ty: a.ty,
|
||||
}))
|
||||
}
|
||||
|
||||
_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
|
||||
}
|
||||
let substs =
|
||||
relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
|
||||
Ok(ConstValue::Unevaluated(a_def_id, &substs))
|
||||
}
|
||||
_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
|
||||
};
|
||||
new_const_val.map(|val| tcx.mk_const(ty::Const {
|
||||
val,
|
||||
ty: a.ty,
|
||||
}))
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
|
||||
|
@ -1265,7 +1265,13 @@ fn collect_const<'tcx>(
|
||||
) {
|
||||
debug!("visiting const {:?}", constant);
|
||||
|
||||
match constant.val {
|
||||
let substituted_constant = if let ConstValue::Param(param) = constant.val {
|
||||
param_substs.const_at(param.index as usize)
|
||||
} else {
|
||||
constant
|
||||
};
|
||||
|
||||
match substituted_constant.val {
|
||||
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
|
||||
collect_miri(tcx, ptr.alloc_id, output),
|
||||
ConstValue::Slice { data: alloc, start: _, end: _ } |
|
||||
@ -1297,7 +1303,7 @@ fn collect_const<'tcx>(
|
||||
tcx.def_span(def_id), "collection encountered polymorphic constant",
|
||||
),
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
20
src/test/ui/const-generics/fn-const-param-call.rs
Normal file
20
src/test/ui/const-generics/fn-const-param-call.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
fn function() -> u32 {
|
||||
17
|
||||
}
|
||||
|
||||
struct Wrapper<const F: fn() -> u32>;
|
||||
|
||||
impl<const F: fn() -> u32> Wrapper<{F}> {
|
||||
fn call() -> u32 {
|
||||
F()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(Wrapper::<{function}>::call(), 17);
|
||||
}
|
8
src/test/ui/const-generics/fn-const-param-call.stderr
Normal file
8
src/test/ui/const-generics/fn-const-param-call.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/fn-const-param-call.rs:3:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
26
src/test/ui/const-generics/fn-const-param-infer.rs
Normal file
26
src/test/ui/const-generics/fn-const-param-infer.rs
Normal file
@ -0,0 +1,26 @@
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
struct Checked<const F: fn(usize) -> bool>;
|
||||
|
||||
fn not_one(val: usize) -> bool { val != 1 }
|
||||
fn not_two(val: usize) -> bool { val != 2 }
|
||||
|
||||
fn generic_arg<T>(val: T) -> bool { true }
|
||||
|
||||
fn generic<T>(val: usize) -> bool { val != 1 }
|
||||
|
||||
fn main() {
|
||||
let _: Option<Checked<{not_one}>> = None;
|
||||
let _: Checked<{not_one}> = Checked::<{not_one}>;
|
||||
let _: Checked<{not_one}> = Checked::<{not_two}>; //~ mismatched types
|
||||
|
||||
let _ = Checked::<{generic_arg}>;
|
||||
let _ = Checked::<{generic_arg::<usize>}>;
|
||||
let _ = Checked::<{generic_arg::<u32>}>; //~ mismatched types
|
||||
|
||||
let _ = Checked::<{generic}>; //~ type annotations needed
|
||||
let _ = Checked::<{generic::<u16>}>;
|
||||
let _: Checked<{generic::<u16>}> = Checked::<{generic::<u16>}>;
|
||||
let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>; //~ mismatched types
|
||||
}
|
45
src/test/ui/const-generics/fn-const-param-infer.stderr
Normal file
45
src/test/ui/const-generics/fn-const-param-infer.stderr
Normal file
@ -0,0 +1,45 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/fn-const-param-infer.rs:1:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-const-param-infer.rs:16:33
|
||||
|
|
||||
LL | let _: Checked<{not_one}> = Checked::<{not_two}>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(1).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(10).0x0) : fn(usize) -> bool`
|
||||
|
|
||||
= note: expected type `Checked<>`
|
||||
found type `Checked<>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-const-param-infer.rs:20:24
|
||||
|
|
||||
LL | let _ = Checked::<{generic_arg::<u32>}>;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected usize, found u32
|
||||
|
|
||||
= note: expected type `fn(usize) -> bool`
|
||||
found type `fn(u32) -> bool {generic_arg::<u32>}`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/fn-const-param-infer.rs:22:24
|
||||
|
|
||||
LL | let _ = Checked::<{generic}>;
|
||||
| ^^^^^^^ cannot infer type for `T`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-const-param-infer.rs:25:40
|
||||
|
|
||||
LL | let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(7).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(20).0x0) : fn(usize) -> bool`
|
||||
|
|
||||
= note: expected type `Checked<>`
|
||||
found type `Checked<>`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0308.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
Loading…
Reference in New Issue
Block a user