Skip to content

[WIP] Rework the entire const trait system #96077

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
cc5960c
Add new generic param
fee1-dead Apr 13, 2022
1933ba7
Add GenericArgDefKind::Constness and tweak generics_of
fee1-dead Apr 13, 2022
0f0f917
Small fixups
oli-obk May 31, 2022
7014e40
Update rustc_{infer,resolve,typeck,trait_selection}
fee1-dead Apr 15, 2022
1bafdc2
Fix more trivial errors
fee1-dead May 7, 2022
ab19ef3
Address trivial lints
oli-obk May 9, 2022
429f9e1
rustc_const_eval
oli-obk May 9, 2022
d9b6e50
runtime matches fall back to non-const PartialEq.
oli-obk May 9, 2022
821bb1f
Small fixups
oli-obk May 31, 2022
67e3eb3
Infer constness params from context if missing
oli-obk May 9, 2022
1b70638
Port some more crates
oli-obk May 9, 2022
11026ec
Update mir typeck
oli-obk May 9, 2022
6ce5109
typeck and borrowck compile
oli-obk May 9, 2022
7d3ee99
Get rustc_privacy to compile
oli-obk May 9, 2022
537b869
rustdoc
oli-obk May 9, 2022
69e6e63
clippy
oli-obk May 9, 2022
dd7ec37
Start poking ICEs until they melt
oli-obk May 9, 2022
77b4af3
Fix assertion ICE
fee1-dead May 10, 2022
17339ca
Add more information to substitution failure
oli-obk May 11, 2022
826f29d
Only add constness arg for const_trait traits
oli-obk May 11, 2022
0d5b724
Print GenericArg
fee1-dead May 11, 2022
e70e92e
Explicitly handle constness from parents
oli-obk May 11, 2022
7c5527d
Now that constness is optional, we default to not-const if it isn't t…
oli-obk May 11, 2022
0fe3432
Constness is optional now
oli-obk May 11, 2022
56a16f8
Remove constness arg from `mk_substs_trait`
oli-obk May 11, 2022
1727172
Remove the helper-methods for mk_substs_trait
oli-obk May 11, 2022
71bcd35
Stop appending constness to all substs
oli-obk May 11, 2022
c59a58c
Allow the constness argument anywhere in the generics list
oli-obk May 31, 2022
b8675a2
HACK: Remove all const trait impls and `~const` from libcore/libstd
oli-obk Jun 1, 2022
03d3d0d
Fix up some trivial test changes
oli-obk Jun 1, 2022
2b7ec4f
Require explicitly handling the tristate constness
oli-obk Jun 1, 2022
4c0f2d0
Actually substitute constness params
oli-obk Jun 1, 2022
d0db6fe
Some tracing for better debugging
oli-obk Jun 1, 2022
4a58caa
Fix typeck probing code to use constness from FnCtxt
fee1-dead Jun 3, 2022
57493e5
Introduce ConstnessArg::Infer and fix some tests
fee1-dead Jun 4, 2022
cbb2cf8
Handle matches added by rebase
fee1-dead Jun 4, 2022
ad467ae
More attempts to fix ui errors
fee1-dead Jun 6, 2022
84054f7
Merge ::Required and ::Param
fee1-dead Jun 6, 2022
cd2edf6
Add CosntnessArg::Const when needed
fee1-dead Jun 7, 2022
d4551d2
Fixed error with more TODOs
fee1-dead Jun 15, 2022
a319331
Don't require has_self when adding constness
fee1-dead Jun 17, 2022
d2322b2
Return unimplemented when feature is not enabled
fee1-dead Jun 19, 2022
cb8bde3
const impls have constness
fee1-dead Jun 19, 2022
6dfe452
var_for_def uses actual constness sometimes
fee1-dead Jun 19, 2022
a0cd8a2
Fix more ui tests
fee1-dead Jun 20, 2022
1ee0614
Equate candidates modulo constness
fee1-dead Jun 20, 2022
7316ca4
Revert "HACK: Remove all const trait impls and `~const` from libcore/…
fee1-dead Jun 20, 2022
25be7a4
attempt to fix std ice
fee1-dead Jun 21, 2022
4f50485
More attempts to fix ICE
fee1-dead Jun 26, 2022
4845b35
general fixes
fee1-dead Jul 13, 2022
b8bbee6
fixup
fee1-dead Jul 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
(
GenericArgKind::Lifetime(_)
| GenericArgKind::Type(_)
| GenericArgKind::Constness(_)
| GenericArgKind::Const(_),
_,
) => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ fn check_opaque_type_parameter_valid(
matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
}
GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
GenericArgKind::Constness(_) => false,
};

if arg_is_param {
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.prove_predicates(
Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}))),
locations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
.type_must_outlive(origin, t1, r2);
}

GenericArgKind::Const(_) => {
GenericArgKind::Constness(_) | GenericArgKind::Const(_) => {
// Consts cannot outlive one another, so we
// don't need to handle any relations here.
}
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2026,6 +2026,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let trait_ref = ty::TraitRef {
def_id: tcx
.require_lang_item(LangItem::CoerceUnsized, Some(self.last_span)),
// TODO: pick constness arg from context
substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]),
};

Expand Down Expand Up @@ -2603,7 +2604,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
(outlives_requirements.category, outlives_requirements.blame_span),
))
}
GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
GenericArgKind::Type(_)
| GenericArgKind::Const(_)
| GenericArgKind::Constness(_) => None,
}
})
.collect();
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
assert!(key.param_env.is_const());
// see comment in eval_to_allocation_raw_provider for what we're doing here
if key.param_env.reveal() == Reveal::All {
let mut key = key;
Expand Down Expand Up @@ -261,7 +260,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
assert!(key.param_env.is_const());
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} else {
self.param_env
};
let param_env = param_env.with_const();
// Use a precise span for better cycle errors.
let val = self.tcx.at(self.cur_span()).eval_to_allocation_raw(param_env.and(gid))?;
self.raw_const_to_mplace(val)
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_const_eval/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,9 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {

// No constraints on lifetimes or constants, except potentially
// constants' types, but `walk` will get to them as well.
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue,
GenericArgKind::Constness(_)
| GenericArgKind::Lifetime(_)
| GenericArgKind::Const(_) => continue,
};

match *ty.kind() {
Expand Down Expand Up @@ -720,10 +722,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
return;
}

let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
let trait_ref = TraitRef::from_method(tcx, trait_id, substs).with_const(tcx);
let poly_trait_pred = Binder::dummy(TraitPredicate {
trait_ref,
constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
});
let obligation =
Expand All @@ -735,7 +736,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
});

match implsrc {
Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => {
Ok(Some(ImplSource::Param(_, ty::ConstnessArg::Const))) => {
debug!(
"const_trait_impl: provided {:?} via where-clause in {:?}",
trait_ref, param_env
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_const_eval/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc_middle::ty::{
suggest_constraining_type_param, Adt, Closure, DefIdTree, FnDef, FnPtr, Param, TraitPredicate,
Ty,
};
use rustc_middle::ty::{Binder, BoundConstness, ImplPolarity, TraitRef};
use rustc_middle::ty::{Binder, ImplPolarity, TraitRef};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{BytePos, Pos, Span, Symbol};
Expand Down Expand Up @@ -150,7 +150,6 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
param_env,
Binder::dummy(TraitPredicate {
trait_ref,
constness: BoundConstness::NotConst,
polarity: ImplPolarity::Positive,
}),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,8 @@ impl Qualif for NeedsNonConstDrop {
ty::Binder::dummy(ty::TraitPredicate {
trait_ref: ty::TraitRef {
def_id: destruct,
substs: cx.tcx.mk_substs_trait(ty, &[]),
substs: cx.tcx.mk_substs_trait(ty, &[ty::ConstnessArg::Const.into()]),
},
constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
}),
);
Expand All @@ -177,8 +176,7 @@ impl Qualif for NeedsNonConstDrop {

if !matches!(
impl_src,
ImplSource::ConstDestruct(_)
| ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::ConstnessArg::Const)
) {
// If our const destruct candidate is not ConstDestruct or implied by the param env,
// then it's bad
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
opt_values[b] = Some(*original_value);
}
}
GenericArgKind::Constness(_) => {}
}
}

Expand Down Expand Up @@ -571,6 +572,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
// encounter this branch.
span_bug!(cause.span, "unexpected const outlives {:?}", predicate);
}
GenericArgKind::Constness(_) => {
span_bug!(cause.span, "unexpected constness outlives {:?}", predicate);
}
};
let predicate = predicate.rebind(atom).to_predicate(self.tcx);

Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_infer/src/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,15 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
_ => relate::super_relate_consts(self, c, c),
}
}

fn constness_args(
&mut self,
a: ty::ConstnessArg,
b: ty::ConstnessArg,
) -> RelateResult<'tcx, ty::ConstnessArg> {
assert_eq!(a, b);
Ok(a)
}
}

pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> {
Expand Down Expand Up @@ -998,4 +1007,12 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
_ => relate::super_relate_consts(self, c, c),
}
}
fn constness_args(
&mut self,
a: ty::ConstnessArg,
b: ty::ConstnessArg,
) -> RelateResult<'tcx, ty::ConstnessArg> {
assert_eq!(a, b);
Ok(a)
}
}
11 changes: 11 additions & 0 deletions compiler/rustc_infer/src/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
}
Ok(a)
}

fn constness_args(
&mut self,
a: ty::ConstnessArg,
b: ty::ConstnessArg,
) -> RelateResult<'tcx, ty::ConstnessArg> {
match (a, b) {
(ty::ConstnessArg::Infer, x) | (x, ty::ConstnessArg::Infer) => Ok(x),
_ => relate::super_relate_constness(self, a, b),
}
}
}

impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
// TODO ?
GenericArgKind::Constness(_) => bug!("unexpected constness arg"),
}
}

Expand Down Expand Up @@ -616,7 +618,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {

/// Computes cost for the given source.
///
/// Sources with a small cost are prefer and should result
/// Sources with a small cost are preferred and should result
/// in a clearer and idiomatic suggestion.
fn source_cost(&self, source: &InferSource<'tcx>) -> usize {
#[derive(Clone, Copy)]
Expand All @@ -629,6 +631,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
GenericArgKind::Lifetime(_) => 0, // erased
GenericArgKind::Type(ty) => self.ty_cost(ty),
GenericArgKind::Const(_) => 3, // some non-zero value
GenericArgKind::Constness(_) => 1,
}
}
fn ty_cost(self, ty: Ty<'tcx>) -> usize {
Expand Down Expand Up @@ -746,6 +749,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
}
match inner.unpack() {
GenericArgKind::Lifetime(_) => {}
GenericArgKind::Constness(_) => {}
GenericArgKind::Type(ty) => {
if matches!(ty.kind(), ty::Opaque(..) | ty::Closure(..) | ty::Generator(..)) {
// Opaque types can't be named by the user right now.
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_infer/src/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::Subtype;

use crate::infer::combine::ConstEquateRelation;
use crate::traits::{ObligationCause, PredicateObligation};
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt};

/// "Greatest lower bound" (common subtype)
Expand Down Expand Up @@ -110,6 +110,15 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
}
}

fn constness_args(
&mut self,
a: ty::ConstnessArg,
b: ty::ConstnessArg,
) -> RelateResult<'tcx, ty::ConstnessArg> {
// TODO.
relate::super_relate_constness(self, a, b)
}
}

impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> {
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_infer/src/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::Subtype;

use crate::infer::combine::ConstEquateRelation;
use crate::traits::{ObligationCause, PredicateObligation};
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::relate::{super_relate_constness, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt};

/// "Least upper bound" (common supertype)
Expand Down Expand Up @@ -110,6 +110,14 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
}
}

fn constness_args(
&mut self,
a: ty::ConstnessArg,
b: ty::ConstnessArg,
) -> RelateResult<'tcx, ty::ConstnessArg> {
super_relate_constness(self, a, b)
}
}

impl<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.next_region_var_in_universe(RegionVariableOrigin::Nll(origin), universe)
}

pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef, constness: Option<ty::ConstnessArg>) -> GenericArg<'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
// Create a region inference variable for the given
Expand Down Expand Up @@ -1199,13 +1199,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
});
self.tcx.mk_const_var(const_var_id, self.tcx.type_of(param.def_id)).into()
}
GenericParamDefKind::Constness => constness.unwrap_or(ty::ConstnessArg::Infer).into(),
}
}

/// Given a set of generics defined on a type or impl, returns a substitution mapping each
/// type/region parameter to a fresh inference variable.
pub fn fresh_substs_for_item(&self, span: Span, def_id: DefId) -> SubstsRef<'tcx> {
InternalSubsts::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param))
InternalSubsts::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param, None))
}

/// Returns `true` if errors have been reported since this infcx was
Expand Down Expand Up @@ -1752,7 +1753,7 @@ impl<'tcx> TyOrConstInferVar<'tcx> {
match arg.unpack() {
GenericArgKind::Type(ty) => Self::maybe_from_ty(ty),
GenericArgKind::Const(ct) => Self::maybe_from_const(ct),
GenericArgKind::Lifetime(_) => None,
GenericArgKind::Lifetime(_) | GenericArgKind::Constness(_) => None,
}
}

Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_infer/src/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,15 @@ where

Ok(a)
}

fn constness_args(
&mut self,
a: ty::ConstnessArg,
b: ty::ConstnessArg,
) -> RelateResult<'tcx, ty::ConstnessArg> {
// TODO.
relate::super_relate_constness(self, a, b)
}
}

impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
Expand Down Expand Up @@ -1077,4 +1086,13 @@ where
self.first_free_index.shift_out(1);
Ok(a.rebind(result))
}

fn constness_args(
&mut self,
a: ty::ConstnessArg,
b: ty::ConstnessArg,
) -> RelateResult<'tcx, ty::ConstnessArg> {
// TODO
relate::super_relate_constness(self, a, b)
}
}
4 changes: 3 additions & 1 deletion compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.iter()
.filter_map(|arg| match arg.unpack() {
GenericArgKind::Lifetime(r) => Some(r),
GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
GenericArgKind::Type(_)
| GenericArgKind::Const(_)
| GenericArgKind::Constness(_) => None,
})
.chain(std::iter::once(self.tcx.lifetimes.re_static))
.collect(),
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_infer/src/infer/outlives/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ fn compute_components<'tcx>(
GenericArgKind::Const(_) => {
compute_components_recursive(tcx, child, out, visited);
}
// TODO ?
GenericArgKind::Constness(_) => {}
}
}
}
Expand Down Expand Up @@ -210,6 +212,8 @@ fn compute_components_recursive<'tcx>(
GenericArgKind::Const(_) => {
compute_components_recursive(tcx, child, out, visited);
}
// TODO ?
GenericArgKind::Constness(_) => {}
}
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ where
GenericArgKind::Const(_) => {
// Const parameters don't impose constraints.
}
// TODO ?
GenericArgKind::Constness(_) => {}
}
}

Expand Down
Loading