mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-03 10:33:34 +00:00
Fully implement ConstArgHasType
This commit is contained in:
parent
a9702a6668
commit
8d6705cdb8
@ -616,6 +616,8 @@ pub enum SelectionError<'tcx> {
|
|||||||
/// We can thus not know whether the hidden type implements an auto trait, so
|
/// We can thus not know whether the hidden type implements an auto trait, so
|
||||||
/// we should not presume anything about it.
|
/// we should not presume anything about it.
|
||||||
OpaqueTypeAutoTraitLeakageUnknown(DefId),
|
OpaqueTypeAutoTraitLeakageUnknown(DefId),
|
||||||
|
/// Error for a `ConstArgHasType` goal
|
||||||
|
ConstArgHasWrongType { ct: ty::Const<'tcx>, ct_ty: Ty<'tcx>, expected_ty: Ty<'tcx> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, TypeVisitable)]
|
#[derive(Clone, Debug, TypeVisitable)]
|
||||||
|
@ -934,6 +934,30 @@ pub struct Placeholder<T> {
|
|||||||
pub universe: UniverseIndex,
|
pub universe: UniverseIndex,
|
||||||
pub bound: T,
|
pub bound: T,
|
||||||
}
|
}
|
||||||
|
impl Placeholder<BoundVar> {
|
||||||
|
pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
|
||||||
|
let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
|
||||||
|
// `ConstArgHasType` are never desugared to be higher ranked.
|
||||||
|
match clause.kind().skip_binder() {
|
||||||
|
ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => {
|
||||||
|
assert!(!(placeholder_ct, ty).has_escaping_bound_vars());
|
||||||
|
|
||||||
|
match placeholder_ct.kind() {
|
||||||
|
ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => {
|
||||||
|
Some(ty)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let ty = candidates.next().unwrap();
|
||||||
|
assert!(candidates.next().is_none());
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type PlaceholderRegion = Placeholder<BoundRegion>;
|
pub type PlaceholderRegion = Placeholder<BoundRegion>;
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ use rustc_span::symbol::{sym, Symbol};
|
|||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
|
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
|
use rustc_type_ir::visit::TypeVisitableExt;
|
||||||
use std::assert_matches::debug_assert_matches;
|
use std::assert_matches::debug_assert_matches;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
@ -339,6 +340,27 @@ impl ParamConst {
|
|||||||
pub fn for_def(def: &ty::GenericParamDef) -> ParamConst {
|
pub fn for_def(def: &ty::GenericParamDef) -> ParamConst {
|
||||||
ParamConst::new(def.index, def.name)
|
ParamConst::new(def.index, def.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
|
||||||
|
let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
|
||||||
|
// `ConstArgHasType` are never desugared to be higher ranked.
|
||||||
|
match clause.kind().skip_binder() {
|
||||||
|
ty::ClauseKind::ConstArgHasType(param_ct, ty) => {
|
||||||
|
assert!(!(param_ct, ty).has_escaping_bound_vars());
|
||||||
|
|
||||||
|
match param_ct.kind() {
|
||||||
|
ty::ConstKind::Param(param_ct) if param_ct.index == self.index => Some(ty),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let ty = candidates.next().unwrap();
|
||||||
|
assert!(candidates.next().is_none());
|
||||||
|
ty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||||
|
@ -200,30 +200,37 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
|||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
let (ct, ty) = goal.predicate;
|
let (ct, ty) = goal.predicate;
|
||||||
|
|
||||||
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
|
let ct_ty = match ct.kind() {
|
||||||
// other than `ConstKind::Value`. Unfortunately this would require looking in the
|
|
||||||
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
|
|
||||||
// have not yet gotten around to implementing this though.
|
|
||||||
//
|
|
||||||
// We do still stall on infer vars though as otherwise a goal like:
|
|
||||||
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
|
|
||||||
// get unified with some const that is not of type `usize`.
|
|
||||||
match ct.kind() {
|
|
||||||
// FIXME: Ignore effect vars because canonicalization doesn't handle them correctly
|
// FIXME: Ignore effect vars because canonicalization doesn't handle them correctly
|
||||||
// and if we stall on the var then we wind up creating ambiguity errors in a probe
|
// and if we stall on the var then we wind up creating ambiguity errors in a probe
|
||||||
// for this goal which contains an effect var. Which then ends up ICEing.
|
// for this goal which contains an effect var. Which then ends up ICEing.
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
|
ty::ConstKind::Infer(ty::InferConst::EffectVar(_)) => {
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||||
|
}
|
||||||
|
ty::ConstKind::Infer(_) => {
|
||||||
|
return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
|
||||||
}
|
}
|
||||||
ty::ConstKind::Error(_) => {
|
ty::ConstKind::Error(_) => {
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||||
}
|
}
|
||||||
_ => {
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
// THISPR
|
self.interner().type_of(uv.def).instantiate(self.interner(), uv.args)
|
||||||
self.eq(goal.param_env, todo!(), ty)?;
|
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
|
||||||
}
|
}
|
||||||
}
|
ty::ConstKind::Expr(_) => unimplemented!(
|
||||||
|
"`feature(generic_const_exprs)` is not supported in the new trait solver"
|
||||||
|
),
|
||||||
|
ty::ConstKind::Param(_) => {
|
||||||
|
unreachable!("`ConstKind::Param` should have been canonicalized to `Placeholder`")
|
||||||
|
}
|
||||||
|
ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
|
||||||
|
ty::ConstKind::Value(ty, _) => ty,
|
||||||
|
ty::ConstKind::Placeholder(placeholder) => {
|
||||||
|
placeholder.find_const_ty_from_env(goal.param_env)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.eq(goal.param_env, ct_ty, ty)?;
|
||||||
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,57 +876,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
|
// Errors for `ConstEvaluatable` predicates show up as
|
||||||
// Errors for `ConstEvaluatable` predicates show up as
|
// `SelectionError::ConstEvalFailure`,
|
||||||
// `SelectionError::ConstEvalFailure`,
|
// not `Unimplemented`.
|
||||||
// not `Unimplemented`.
|
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||||
|
// Errors for `ConstEquate` predicates show up as
|
||||||
|
// `SelectionError::ConstEvalFailure`,
|
||||||
|
// not `Unimplemented`.
|
||||||
|
| ty::PredicateKind::ConstEquate { .. }
|
||||||
|
// Ambiguous predicates should never error
|
||||||
|
| ty::PredicateKind::Ambiguous
|
||||||
|
| ty::PredicateKind::NormalizesTo { .. }
|
||||||
|
| ty::PredicateKind::AliasRelate { .. }
|
||||||
|
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
span,
|
span,
|
||||||
"const-evaluatable requirement gave wrong error: `{:?}`",
|
"Unexpected `Predicate` for `SelectionError`: `{:?}`",
|
||||||
obligation
|
obligation
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::ConstEquate(..) => {
|
|
||||||
// Errors for `ConstEquate` predicates show up as
|
|
||||||
// `SelectionError::ConstEvalFailure`,
|
|
||||||
// not `Unimplemented`.
|
|
||||||
span_bug!(
|
|
||||||
span,
|
|
||||||
"const-equate requirement gave wrong error: `{:?}`",
|
|
||||||
obligation
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
|
|
||||||
|
|
||||||
ty::PredicateKind::NormalizesTo(..) => span_bug!(
|
|
||||||
span,
|
|
||||||
"NormalizesTo predicate should never be the predicate cause of a SelectionError"
|
|
||||||
),
|
|
||||||
|
|
||||||
ty::PredicateKind::AliasRelate(..) => span_bug!(
|
|
||||||
span,
|
|
||||||
"AliasRelate predicate should never be the predicate cause of a SelectionError"
|
|
||||||
),
|
|
||||||
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
|
||||||
let mut diag = self.dcx().struct_span_err(
|
|
||||||
span,
|
|
||||||
format!("the constant `{ct}` is not of type `{ty}`"),
|
|
||||||
);
|
|
||||||
self.note_type_err(
|
|
||||||
&mut diag,
|
|
||||||
&obligation.cause,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
// THISPR
|
|
||||||
TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, todo!())),
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
diag
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -989,6 +957,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
Overflow(_) => {
|
Overflow(_) => {
|
||||||
bug!("overflow should be handled before the `report_selection_error` path");
|
bug!("overflow should be handled before the `report_selection_error` path");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => {
|
||||||
|
let mut diag = self.dcx().struct_span_err(
|
||||||
|
span,
|
||||||
|
format!("the constant `{ct}` is not of type `{expected_ty}`"),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.note_type_err(
|
||||||
|
&mut diag,
|
||||||
|
&obligation.cause,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
diag
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.note_obligation_cause(&mut err, &obligation);
|
self.note_obligation_cause(&mut err, &obligation);
|
||||||
|
@ -439,38 +439,50 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||||||
// This is because this is not ever a useful obligation to report
|
// This is because this is not ever a useful obligation to report
|
||||||
// as the cause of an overflow.
|
// as the cause of an overflow.
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||||
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
|
let ct = infcx.shallow_resolve_const(ct);
|
||||||
// other than `ConstKind::Value`. Unfortunately this would require looking in the
|
let ct_ty = match ct.kind() {
|
||||||
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
|
ty::ConstKind::Infer(var) => {
|
||||||
// don't really want to implement this in the old solver so I haven't.
|
let var = match var {
|
||||||
//
|
ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
|
||||||
// We do still stall on infer vars though as otherwise a goal like:
|
ty::InferConst::EffectVar(vid) => TyOrConstInferVar::Effect(vid),
|
||||||
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
|
ty::InferConst::Fresh(_) => {
|
||||||
// get unified with some const that is not of type `usize`.
|
bug!("encountered fresh const in fulfill")
|
||||||
let ct = self.selcx.infcx.shallow_resolve_const(ct);
|
}
|
||||||
match ct.kind() {
|
};
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
|
||||||
pending_obligation.stalled_on.clear();
|
pending_obligation.stalled_on.clear();
|
||||||
pending_obligation.stalled_on.extend([TyOrConstInferVar::Const(vid)]);
|
pending_obligation.stalled_on.extend([var]);
|
||||||
ProcessResult::Unchanged
|
return ProcessResult::Unchanged;
|
||||||
}
|
}
|
||||||
ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]),
|
ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]),
|
||||||
_ => {
|
ty::ConstKind::Value(ty, _) => ty,
|
||||||
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
// Only really excercised by generic_const_exprs
|
infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
|
||||||
DefineOpaqueTypes::Yes,
|
|
||||||
// THISPR
|
|
||||||
todo!(),
|
|
||||||
ty,
|
|
||||||
) {
|
|
||||||
Ok(inf_ok) => {
|
|
||||||
ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
|
|
||||||
}
|
|
||||||
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
|
|
||||||
SelectionError::Unimplemented,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// FIXME(generic_const_exprs): we should construct an alias like
|
||||||
|
// `<lhs_ty as Add<rhs_ty>>::Output` when this is an `Expr` representing
|
||||||
|
// `lhs + rhs`.
|
||||||
|
ty::ConstKind::Expr(_) => {
|
||||||
|
return ProcessResult::Changed(mk_pending(vec![]));
|
||||||
|
}
|
||||||
|
ty::ConstKind::Placeholder(_) => {
|
||||||
|
bug!("placeholder const {:?} in old solver", ct)
|
||||||
|
}
|
||||||
|
ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
|
||||||
|
ty::ConstKind::Param(param_ct) => {
|
||||||
|
param_ct.find_ty_from_env(obligation.param_env)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match infcx.at(&obligation.cause, obligation.param_env).eq(
|
||||||
|
// Only really excercised by generic_const_exprs
|
||||||
|
DefineOpaqueTypes::Yes,
|
||||||
|
ct_ty,
|
||||||
|
ty,
|
||||||
|
) {
|
||||||
|
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
|
||||||
|
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
|
||||||
|
SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty },
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -994,23 +994,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
|
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||||
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
|
|
||||||
// other than `ConstKind::Value`. Unfortunately this would require looking in the
|
|
||||||
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
|
|
||||||
// don't really want to implement this in the old solver so I haven't.
|
|
||||||
//
|
|
||||||
// We do still stall on infer vars though as otherwise a goal like:
|
|
||||||
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
|
|
||||||
// get unified with some const that is not of type `usize`.
|
|
||||||
let ct = self.infcx.shallow_resolve_const(ct);
|
let ct = self.infcx.shallow_resolve_const(ct);
|
||||||
let ct_ty = match ct.kind() {
|
let ct_ty = match ct.kind() {
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
|
ty::ConstKind::Infer(_) => {
|
||||||
return Ok(EvaluatedToAmbig);
|
return Ok(EvaluatedToAmbig);
|
||||||
}
|
}
|
||||||
ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),
|
ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),
|
||||||
// THISPR
|
ty::ConstKind::Value(ty, _) => ty,
|
||||||
_ => todo!(),
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
// _ => ct.ty(),
|
self.tcx().type_of(uv.def).instantiate(self.tcx(), uv.args)
|
||||||
|
}
|
||||||
|
// FIXME(generic_const_exprs): See comment in `fulfill.rs`
|
||||||
|
ty::ConstKind::Expr(_) => return Ok(EvaluatedToOk),
|
||||||
|
ty::ConstKind::Placeholder(_) => {
|
||||||
|
bug!("placeholder const {:?} in old solver", ct)
|
||||||
|
}
|
||||||
|
ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
|
||||||
|
ty::ConstKind::Param(param_ct) => {
|
||||||
|
param_ct.find_ty_from_env(obligation.param_env)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
|
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
|
||||||
|
Loading…
Reference in New Issue
Block a user