Rollup merge of #103488 - oli-obk:impl_trait_for_tait, r=lcnr
Allow opaque types in trait impl headers and rely on coherence to reject unsound cases r? ````@lcnr```` fixes #99840
This commit is contained in:
commit
53eab246db
75 changed files with 545 additions and 313 deletions
|
@ -81,6 +81,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
.normalize_fn_sig_for_diagnostic
|
||||
.as_ref()
|
||||
.map(|f| f.clone()),
|
||||
intercrate: self.intercrate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,11 +23,10 @@ use rustc_index::vec::Idx;
|
|||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::arena::ArenaAllocatable;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::relate::TypeRelation;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
||||
use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, BoundVar, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use std::fmt::Debug;
|
||||
use std::iter;
|
||||
|
@ -729,10 +728,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
|
|||
});
|
||||
}
|
||||
|
||||
fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {
|
||||
span_bug!(self.cause.span(), "generic_const_exprs: unreachable `const_equate`");
|
||||
}
|
||||
|
||||
fn normalization() -> NormalizationStrategy {
|
||||
NormalizationStrategy::Eager
|
||||
}
|
||||
|
@ -741,11 +736,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
|
|||
true
|
||||
}
|
||||
|
||||
fn register_opaque_type_obligations(
|
||||
&mut self,
|
||||
obligations: PredicateObligations<'tcx>,
|
||||
) -> Result<(), TypeError<'tcx>> {
|
||||
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
|
||||
self.obligations.extend(obligations);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -450,6 +450,15 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
ty::Binder::dummy(predicate),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn mark_ambiguous(&mut self) {
|
||||
self.obligations.push(Obligation::new(
|
||||
self.tcx(),
|
||||
self.trace.cause.clone(),
|
||||
self.param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::Ambiguous),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
struct Generalizer<'cx, 'tcx> {
|
||||
|
@ -521,6 +530,11 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
self.infcx.intercrate
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
|
@ -533,6 +547,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||
true
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
span_bug!(self.cause.span, "opaque types are handled in `tys`");
|
||||
}
|
||||
|
||||
fn binders<T>(
|
||||
&mut self,
|
||||
a: ty::Binder<'tcx, T>,
|
||||
|
@ -657,6 +675,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||
// relatable.
|
||||
Ok(t)
|
||||
}
|
||||
ty::Opaque(def_id, substs) => {
|
||||
let s = self.relate(substs, substs)?;
|
||||
Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
|
||||
}
|
||||
_ => relate::super_relate_tys(self, t, t),
|
||||
}?;
|
||||
|
||||
|
@ -799,6 +821,11 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
|
|||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
assert!(!self.infcx.intercrate);
|
||||
false
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
|
@ -811,6 +838,10 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
|
|||
true
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
_variance: ty::Variance,
|
||||
|
|
|
@ -32,6 +32,10 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
|||
self.fields.tcx()
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
self.fields.infcx.intercrate
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.fields.param_env
|
||||
}
|
||||
|
@ -40,6 +44,10 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
|||
self.a_is_expected
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
self.fields.mark_ambiguous();
|
||||
}
|
||||
|
||||
fn relate_item_substs(
|
||||
&mut self,
|
||||
_item_def_id: DefId,
|
||||
|
|
|
@ -2937,6 +2937,11 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
|
|||
self.0.tcx
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
assert!(!self.0.intercrate);
|
||||
false
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
// Unused, only for consts which we treat as always equal
|
||||
ty::ParamEnv::empty()
|
||||
|
@ -2950,6 +2955,10 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
|
|||
true
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: relate::Relate<'tcx>>(
|
||||
&mut self,
|
||||
_variance: ty::Variance,
|
||||
|
|
|
@ -30,6 +30,11 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
|
|||
"Glb"
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
assert!(!self.fields.infcx.intercrate);
|
||||
false
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.fields.tcx()
|
||||
}
|
||||
|
@ -42,6 +47,10 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
|
|||
self.a_is_expected
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!("mark_ambiguous used outside of coherence");
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
|
|
|
@ -30,6 +30,11 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
|
|||
"Lub"
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
assert!(!self.fields.infcx.intercrate);
|
||||
false
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.fields.tcx()
|
||||
}
|
||||
|
@ -42,6 +47,10 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
|
|||
self.a_is_expected
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!("mark_ambiguous used outside of coherence");
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
|
|
|
@ -337,6 +337,26 @@ pub struct InferCtxt<'tcx> {
|
|||
|
||||
normalize_fn_sig_for_diagnostic:
|
||||
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
|
||||
|
||||
/// During coherence we have to assume that other crates may add
|
||||
/// additional impls which we currently don't know about.
|
||||
///
|
||||
/// To deal with this evaluation should be conservative
|
||||
/// and consider the possibility of impls from outside this crate.
|
||||
/// This comes up primarily when resolving ambiguity. Imagine
|
||||
/// there is some trait reference `$0: Bar` where `$0` is an
|
||||
/// inference variable. If `intercrate` is true, then we can never
|
||||
/// say for sure that this reference is not implemented, even if
|
||||
/// there are *no impls at all for `Bar`*, because `$0` could be
|
||||
/// bound to some type that in a downstream crate that implements
|
||||
/// `Bar`.
|
||||
///
|
||||
/// Outside of coherence we set this to false because we are only
|
||||
/// interested in types that the user could actually have written.
|
||||
/// In other words, we consider `$0: Bar` to be unimplemented if
|
||||
/// there is no type that the user could *actually name* that
|
||||
/// would satisfy it. This avoids crippling inference, basically.
|
||||
pub intercrate: bool,
|
||||
}
|
||||
|
||||
/// See the `error_reporting` module for more details.
|
||||
|
@ -552,6 +572,8 @@ pub struct InferCtxtBuilder<'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
defining_use_anchor: DefiningAnchor,
|
||||
considering_regions: bool,
|
||||
/// Whether we are in coherence mode.
|
||||
intercrate: bool,
|
||||
normalize_fn_sig_for_diagnostic:
|
||||
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
|
||||
}
|
||||
|
@ -567,6 +589,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
|||
defining_use_anchor: DefiningAnchor::Error,
|
||||
considering_regions: true,
|
||||
normalize_fn_sig_for_diagnostic: None,
|
||||
intercrate: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -583,6 +606,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn intercrate(mut self) -> Self {
|
||||
self.intercrate = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn ignoring_regions(mut self) -> Self {
|
||||
self.considering_regions = false;
|
||||
self
|
||||
|
@ -622,6 +650,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
defining_use_anchor,
|
||||
considering_regions,
|
||||
ref normalize_fn_sig_for_diagnostic,
|
||||
intercrate,
|
||||
} = *self;
|
||||
InferCtxt {
|
||||
tcx,
|
||||
|
@ -641,6 +670,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic
|
||||
.as_ref()
|
||||
.map(|f| f.clone()),
|
||||
intercrate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::infer::combine::ConstEquateRelation;
|
|||
use crate::infer::InferCtxt;
|
||||
use crate::infer::{ConstVarValue, ConstVariableValue};
|
||||
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use crate::traits::PredicateObligation;
|
||||
use crate::traits::{Obligation, PredicateObligation};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
|
@ -92,11 +92,7 @@ pub trait TypeRelatingDelegate<'tcx> {
|
|||
info: ty::VarianceDiagInfo<'tcx>,
|
||||
);
|
||||
|
||||
fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
|
||||
fn register_opaque_type_obligations(
|
||||
&mut self,
|
||||
obligations: Vec<PredicateObligation<'tcx>>,
|
||||
) -> Result<(), TypeError<'tcx>>;
|
||||
fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
|
||||
|
||||
/// Creates a new universe index. Used when instantiating placeholders.
|
||||
fn create_next_universe(&mut self) -> ty::UniverseIndex;
|
||||
|
@ -419,7 +415,7 @@ where
|
|||
.infcx
|
||||
.handle_opaque_type(a, b, true, &cause, self.delegate.param_env())?
|
||||
.obligations;
|
||||
self.delegate.register_opaque_type_obligations(obligations)?;
|
||||
self.delegate.register_obligations(obligations);
|
||||
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
|
||||
Ok(a)
|
||||
}
|
||||
|
@ -531,6 +527,10 @@ where
|
|||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
self.infcx.intercrate
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.delegate.param_env()
|
||||
}
|
||||
|
@ -543,6 +543,17 @@ where
|
|||
true
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
let cause = ObligationCause::dummy_with_span(self.delegate.span());
|
||||
let param_env = self.delegate.param_env();
|
||||
self.delegate.register_obligations(vec![Obligation::new(
|
||||
self.tcx(),
|
||||
cause,
|
||||
param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::Ambiguous),
|
||||
)]);
|
||||
}
|
||||
|
||||
#[instrument(skip(self, info), level = "trace", ret)]
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
|
@ -800,8 +811,12 @@ impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
|
|||
where
|
||||
D: TypeRelatingDelegate<'tcx>,
|
||||
{
|
||||
fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
|
||||
self.delegate.const_equate(a, b);
|
||||
fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) {
|
||||
// We don't have to worry about the equality of consts during borrow checking
|
||||
// as consts always have a static lifetime.
|
||||
// FIXME(oli-obk): is this really true? We can at least have HKL and with
|
||||
// inline consts we may have further lifetimes that may be unsound to treat as
|
||||
// 'static.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -898,6 +913,11 @@ where
|
|||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
assert!(!self.infcx.intercrate);
|
||||
false
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.delegate.param_env()
|
||||
}
|
||||
|
@ -910,6 +930,10 @@ where
|
|||
true
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
variance: ty::Variance,
|
||||
|
|
|
@ -29,6 +29,7 @@ pub fn explicit_outlives_bounds<'tcx>(
|
|||
| ty::PredicateKind::TypeOutlives(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
|
||||
Some(OutlivesBound::RegionSubRegion(r_b, r_a))
|
||||
|
|
|
@ -136,6 +136,11 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
|
|||
fn tag(&self) -> &'static str {
|
||||
"Match"
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
@ -146,6 +151,10 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
|
|||
true
|
||||
} // irrelevant
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
_: ty::Variance,
|
||||
|
|
|
@ -35,6 +35,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
|||
fn tag(&self) -> &'static str {
|
||||
"Sub"
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
self.fields.infcx.intercrate
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.fields.infcx.tcx
|
||||
}
|
||||
|
@ -47,6 +52,10 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
|||
self.a_is_expected
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
self.fields.mark_ambiguous()
|
||||
}
|
||||
|
||||
fn with_cause<F, R>(&mut self, cause: Cause, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
|
|
|
@ -285,6 +285,7 @@ impl<'tcx> Elaborator<'tcx> {
|
|||
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||
// Nothing to elaborate
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue