Auto merge of #99521 - fee1-dead-contrib:const_fix_hax, r=oli-obk
Fix hack that remaps env constness. WARNING: might have perf implications. Are there any more problems with having a constness in the `ParamEnv` now? :) r? `@oli-obk`
This commit is contained in:
commit
22d25f21dc
@ -575,6 +575,19 @@ pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> {
|
|||||||
|
|
||||||
Some(tcx.mk_predicate(kind))
|
Some(tcx.mk_predicate(kind))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self {
|
||||||
|
if let PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) = self.kind().skip_binder()
|
||||||
|
&& constness != BoundConstness::NotConst
|
||||||
|
{
|
||||||
|
self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Trait(TraitPredicate {
|
||||||
|
trait_ref,
|
||||||
|
constness: BoundConstness::NotConst,
|
||||||
|
polarity,
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
|
||||||
|
@ -31,14 +31,14 @@ pub(crate) fn update<'tcx, T>(
|
|||||||
obligation
|
obligation
|
||||||
.predicate
|
.predicate
|
||||||
.kind()
|
.kind()
|
||||||
.map_bound(|_| {
|
.rebind(
|
||||||
// (*) binder moved here
|
// (*) binder moved here
|
||||||
ty::PredicateKind::Trait(ty::TraitPredicate {
|
ty::PredicateKind::Trait(ty::TraitPredicate {
|
||||||
trait_ref,
|
trait_ref,
|
||||||
constness: tpred.constness,
|
constness: tpred.constness,
|
||||||
polarity: tpred.polarity,
|
polarity: tpred.polarity,
|
||||||
})
|
})
|
||||||
})
|
)
|
||||||
.to_predicate(infcx.tcx),
|
.to_predicate(infcx.tcx),
|
||||||
);
|
);
|
||||||
// Don't report overflow errors. Otherwise equivalent to may_hold.
|
// Don't report overflow errors. Otherwise equivalent to may_hold.
|
||||||
|
@ -42,115 +42,96 @@ pub(super) fn confirm_candidate(
|
|||||||
obligation: &TraitObligation<'tcx>,
|
obligation: &TraitObligation<'tcx>,
|
||||||
candidate: SelectionCandidate<'tcx>,
|
candidate: SelectionCandidate<'tcx>,
|
||||||
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
|
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
|
||||||
let mut obligation = obligation;
|
let mut impl_src = match candidate {
|
||||||
let new_obligation;
|
|
||||||
|
|
||||||
// HACK(const_trait_impl): the surrounding environment is remapped to a non-const context
|
|
||||||
// because nested obligations might be actually `~const` then (incorrectly) requiring
|
|
||||||
// const impls. for example:
|
|
||||||
// ```
|
|
||||||
// pub trait Super {}
|
|
||||||
// pub trait Sub: Super {}
|
|
||||||
//
|
|
||||||
// impl<A> const Super for &A where A: ~const Super {}
|
|
||||||
// impl<A> const Sub for &A where A: ~const Sub {}
|
|
||||||
// ```
|
|
||||||
//
|
|
||||||
// The procedure to check the code above without the remapping code is as follows:
|
|
||||||
// ```
|
|
||||||
// CheckWf(impl const Sub for &A where A: ~const Sub) // <- const env
|
|
||||||
// CheckPredicate(&A: Super)
|
|
||||||
// CheckPredicate(A: ~const Super) // <- still const env, failure
|
|
||||||
// ```
|
|
||||||
if obligation.param_env.is_const() && !obligation.predicate.is_const_if_const() {
|
|
||||||
new_obligation = TraitObligation {
|
|
||||||
cause: obligation.cause.clone(),
|
|
||||||
param_env: obligation.param_env.without_const(),
|
|
||||||
..*obligation
|
|
||||||
};
|
|
||||||
obligation = &new_obligation;
|
|
||||||
}
|
|
||||||
|
|
||||||
match candidate {
|
|
||||||
BuiltinCandidate { has_nested } => {
|
BuiltinCandidate { has_nested } => {
|
||||||
let data = self.confirm_builtin_candidate(obligation, has_nested);
|
let data = self.confirm_builtin_candidate(obligation, has_nested);
|
||||||
Ok(ImplSource::Builtin(data))
|
ImplSource::Builtin(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamCandidate(param) => {
|
ParamCandidate(param) => {
|
||||||
let obligations =
|
let obligations =
|
||||||
self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
|
self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
|
||||||
Ok(ImplSource::Param(obligations, param.skip_binder().constness))
|
ImplSource::Param(obligations, param.skip_binder().constness)
|
||||||
}
|
}
|
||||||
|
|
||||||
ImplCandidate(impl_def_id) => {
|
ImplCandidate(impl_def_id) => {
|
||||||
Ok(ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id)))
|
ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoImplCandidate(trait_def_id) => {
|
AutoImplCandidate(trait_def_id) => {
|
||||||
let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
|
let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
|
||||||
Ok(ImplSource::AutoImpl(data))
|
ImplSource::AutoImpl(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectionCandidate(idx) => {
|
ProjectionCandidate(idx) => {
|
||||||
let obligations = self.confirm_projection_candidate(obligation, idx)?;
|
let obligations = self.confirm_projection_candidate(obligation, idx)?;
|
||||||
// FIXME(jschievink): constness
|
// FIXME(jschievink): constness
|
||||||
Ok(ImplSource::Param(obligations, ty::BoundConstness::NotConst))
|
ImplSource::Param(obligations, ty::BoundConstness::NotConst)
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectCandidate(idx) => {
|
ObjectCandidate(idx) => {
|
||||||
let data = self.confirm_object_candidate(obligation, idx)?;
|
let data = self.confirm_object_candidate(obligation, idx)?;
|
||||||
Ok(ImplSource::Object(data))
|
ImplSource::Object(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
ClosureCandidate => {
|
ClosureCandidate => {
|
||||||
let vtable_closure = self.confirm_closure_candidate(obligation)?;
|
let vtable_closure = self.confirm_closure_candidate(obligation)?;
|
||||||
Ok(ImplSource::Closure(vtable_closure))
|
ImplSource::Closure(vtable_closure)
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneratorCandidate => {
|
GeneratorCandidate => {
|
||||||
let vtable_generator = self.confirm_generator_candidate(obligation)?;
|
let vtable_generator = self.confirm_generator_candidate(obligation)?;
|
||||||
Ok(ImplSource::Generator(vtable_generator))
|
ImplSource::Generator(vtable_generator)
|
||||||
}
|
}
|
||||||
|
|
||||||
FnPointerCandidate { .. } => {
|
FnPointerCandidate { .. } => {
|
||||||
let data = self.confirm_fn_pointer_candidate(obligation)?;
|
let data = self.confirm_fn_pointer_candidate(obligation)?;
|
||||||
Ok(ImplSource::FnPointer(data))
|
ImplSource::FnPointer(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
DiscriminantKindCandidate => {
|
DiscriminantKindCandidate => {
|
||||||
Ok(ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData))
|
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
|
||||||
}
|
}
|
||||||
|
|
||||||
PointeeCandidate => Ok(ImplSource::Pointee(ImplSourcePointeeData)),
|
PointeeCandidate => ImplSource::Pointee(ImplSourcePointeeData),
|
||||||
|
|
||||||
TraitAliasCandidate(alias_def_id) => {
|
TraitAliasCandidate(alias_def_id) => {
|
||||||
let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
|
let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
|
||||||
Ok(ImplSource::TraitAlias(data))
|
ImplSource::TraitAlias(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltinObjectCandidate => {
|
BuiltinObjectCandidate => {
|
||||||
// This indicates something like `Trait + Send: Send`. In this case, we know that
|
// This indicates something like `Trait + Send: Send`. In this case, we know that
|
||||||
// this holds because that's what the object type is telling us, and there's really
|
// this holds because that's what the object type is telling us, and there's really
|
||||||
// no additional obligations to prove and no types in particular to unify, etc.
|
// no additional obligations to prove and no types in particular to unify, etc.
|
||||||
Ok(ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst))
|
ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst)
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltinUnsizeCandidate => {
|
BuiltinUnsizeCandidate => {
|
||||||
let data = self.confirm_builtin_unsize_candidate(obligation)?;
|
let data = self.confirm_builtin_unsize_candidate(obligation)?;
|
||||||
Ok(ImplSource::Builtin(data))
|
ImplSource::Builtin(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
TraitUpcastingUnsizeCandidate(idx) => {
|
TraitUpcastingUnsizeCandidate(idx) => {
|
||||||
let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
|
let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
|
||||||
Ok(ImplSource::TraitUpcasting(data))
|
ImplSource::TraitUpcasting(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstDestructCandidate(def_id) => {
|
ConstDestructCandidate(def_id) => {
|
||||||
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
|
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
|
||||||
Ok(ImplSource::ConstDestruct(data))
|
ImplSource::ConstDestruct(data)
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if !obligation.predicate.is_const_if_const() {
|
||||||
|
// normalize nested predicates according to parent predicate's constness.
|
||||||
|
impl_src = impl_src.map(|mut o| {
|
||||||
|
o.predicate = o.predicate.without_const(self.tcx());
|
||||||
|
o
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(impl_src)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm_projection_candidate(
|
fn confirm_projection_candidate(
|
||||||
|
@ -182,9 +182,9 @@ fn deduce_expectations_from_expected_type(
|
|||||||
ty::PredicateKind::Projection(proj_predicate) => self
|
ty::PredicateKind::Projection(proj_predicate) => self
|
||||||
.deduce_sig_from_projection(
|
.deduce_sig_from_projection(
|
||||||
Some(span.0),
|
Some(span.0),
|
||||||
pred.0.kind().rebind(
|
pred.0
|
||||||
pred.map_bound(|_| proj_predicate).subst(self.tcx, substs),
|
.kind()
|
||||||
),
|
.rebind(pred.rebind(proj_predicate).subst(self.tcx, substs)),
|
||||||
),
|
),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
const Y: &'static [u8] = b"";
|
const Y: &'static [u8] = b"";
|
||||||
&X(*Y)
|
&X(*Y)
|
||||||
//~^ ERROR E0277
|
//~^ ERROR E0277
|
||||||
//~| ERROR E0277
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -8,20 +8,6 @@ LL | &X(*Y)
|
|||||||
= note: all function arguments must have a statically known size
|
= note: all function arguments must have a statically known size
|
||||||
= help: unsized fn params are gated as an unstable feature
|
= help: unsized fn params are gated as an unstable feature
|
||||||
|
|
||||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
error: aborting due to previous error
|
||||||
--> $DIR/issue-30355.rs:5:6
|
|
||||||
|
|
|
||||||
LL | &X(*Y)
|
|
||||||
| ^ doesn't have a size known at compile-time
|
|
||||||
|
|
|
||||||
= help: within `X`, the trait `Sized` is not implemented for `[u8]`
|
|
||||||
note: required because it appears within the type `X`
|
|
||||||
--> $DIR/issue-30355.rs:1:12
|
|
||||||
|
|
|
||||||
LL | pub struct X([u8]);
|
|
||||||
| ^
|
|
||||||
= note: the return type of a function must have a statically known size
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
Loading…
Reference in New Issue
Block a user