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
@ -2,9 +2,8 @@
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_infer::traits::PredicateObligations;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::relate::TypeRelation;
|
||||
use rustc_middle::ty::{self, Const, Ty};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::query::Fallible;
|
||||
|
||||
@ -141,13 +140,6 @@ fn push_outlives(
|
||||
);
|
||||
}
|
||||
|
||||
// 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.
|
||||
fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {}
|
||||
|
||||
fn normalization() -> NormalizationStrategy {
|
||||
NormalizationStrategy::Eager
|
||||
}
|
||||
@ -156,10 +148,7 @@ fn forbid_inference_vars() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn register_opaque_type_obligations(
|
||||
&mut self,
|
||||
obligations: PredicateObligations<'tcx>,
|
||||
) -> Result<(), TypeError<'tcx>> {
|
||||
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
|
||||
self.type_checker
|
||||
.fully_perform_op(
|
||||
self.locations,
|
||||
@ -172,6 +161,5 @@ fn register_opaque_type_obligations(
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -244,6 +244,10 @@ fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
@ -256,6 +260,10 @@ fn a_is_expected(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
_: ty::Variance,
|
||||
|
@ -5,7 +5,6 @@
|
||||
use rustc_errors::{struct_span_err, DelayDm};
|
||||
use rustc_errors::{Diagnostic, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::util::IgnoreRegions;
|
||||
use rustc_middle::ty::{
|
||||
@ -47,58 +46,6 @@ fn do_orphan_check_impl<'tcx>(
|
||||
let sp = tcx.def_span(def_id);
|
||||
let tr = impl_.of_trait.as_ref().unwrap();
|
||||
|
||||
// Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples,
|
||||
// and #84660 where it would otherwise allow unsoundness.
|
||||
if trait_ref.has_opaque_types() {
|
||||
trace!("{:#?}", item);
|
||||
// First we find the opaque type in question.
|
||||
for ty in trait_ref.substs {
|
||||
for ty in ty.walk() {
|
||||
let ty::subst::GenericArgKind::Type(ty) = ty.unpack() else { continue };
|
||||
let ty::Opaque(def_id, _) = *ty.kind() else { continue };
|
||||
trace!(?def_id);
|
||||
|
||||
// Then we search for mentions of the opaque type's type alias in the HIR
|
||||
struct SpanFinder<'tcx> {
|
||||
sp: Span,
|
||||
def_id: DefId,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
impl<'v, 'tcx> hir::intravisit::Visitor<'v> for SpanFinder<'tcx> {
|
||||
#[instrument(level = "trace", skip(self, _id))]
|
||||
fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
|
||||
// You can't mention an opaque type directly, so we look for type aliases
|
||||
if let hir::def::Res::Def(hir::def::DefKind::TyAlias, def_id) = path.res {
|
||||
// And check if that type alias's type contains the opaque type we're looking for
|
||||
for arg in self.tcx.type_of(def_id).walk() {
|
||||
if let GenericArgKind::Type(ty) = arg.unpack() {
|
||||
if let ty::Opaque(def_id, _) = *ty.kind() {
|
||||
if def_id == self.def_id {
|
||||
// Finally we update the span to the mention of the type alias
|
||||
self.sp = path.span;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::intravisit::walk_path(self, path)
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = SpanFinder { sp, def_id, tcx };
|
||||
hir::intravisit::walk_item(&mut visitor, item);
|
||||
let reported = tcx
|
||||
.sess
|
||||
.struct_span_err(visitor.sp, "cannot implement trait on type alias impl trait")
|
||||
.span_note(tcx.def_span(def_id), "type alias impl trait defined here")
|
||||
.emit();
|
||||
return Err(reported);
|
||||
}
|
||||
}
|
||||
span_bug!(sp, "opaque type not found, but `has_opaque_types` is set")
|
||||
}
|
||||
|
||||
match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
|
||||
Ok(()) => {}
|
||||
Err(err) => emit_orphan_check_error(
|
||||
|
@ -517,6 +517,7 @@ fn trait_predicate_kind<'tcx>(
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ pub(crate) fn explicit_predicates_of(
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
|
||||
}
|
||||
}
|
||||
|
@ -702,6 +702,7 @@ pub(in super::super) fn obligations_for_self_ty<'b>(
|
||||
// code is looking for a self type of an unresolved
|
||||
// inference variable.
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
},
|
||||
)
|
||||
|
@ -803,6 +803,7 @@ fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
|
||||
| ty::PredicateKind::TypeOutlives(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
}
|
||||
});
|
||||
|
@ -81,6 +81,7 @@ pub fn fork(&self) -> Self {
|
||||
.normalize_fn_sig_for_diagnostic
|
||||
.as_ref()
|
||||
.map(|f| f.clone()),
|
||||
intercrate: self.intercrate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,10 @@
|
||||
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 @@ fn push_outlives(
|
||||
});
|
||||
}
|
||||
|
||||
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 @@ fn forbid_inference_vars() -> bool {
|
||||
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 @@ pub fn add_const_equate_obligation(
|
||||
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 @@ fn a_is_expected(&self) -> bool {
|
||||
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 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'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 @@ fn tcx(&self) -> TyCtxt<'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 @@ fn a_is_expected(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
_variance: ty::Variance,
|
||||
|
@ -32,6 +32,10 @@ fn tcx(&self) -> TyCtxt<'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 @@ fn a_is_expected(&self) -> bool {
|
||||
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 @@ fn tcx(&self) -> TyCtxt<'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 @@ fn a_is_expected(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: relate::Relate<'tcx>>(
|
||||
&mut self,
|
||||
_variance: ty::Variance,
|
||||
|
@ -30,6 +30,11 @@ fn tag(&self) -> &'static str {
|
||||
"Glb"
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
assert!(!self.fields.infcx.intercrate);
|
||||
false
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.fields.tcx()
|
||||
}
|
||||
@ -42,6 +47,10 @@ fn a_is_expected(&self) -> bool {
|
||||
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 @@ fn tag(&self) -> &'static str {
|
||||
"Lub"
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
assert!(!self.fields.infcx.intercrate);
|
||||
false
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.fields.tcx()
|
||||
}
|
||||
@ -42,6 +47,10 @@ fn a_is_expected(&self) -> bool {
|
||||
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 @@ fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
|
||||
defining_use_anchor: DefiningAnchor::Error,
|
||||
considering_regions: true,
|
||||
normalize_fn_sig_for_diagnostic: None,
|
||||
intercrate: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -583,6 +606,11 @@ pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor)
|
||||
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 @@ pub fn build(&mut self) -> InferCtxt<'tcx> {
|
||||
defining_use_anchor,
|
||||
considering_regions,
|
||||
ref normalize_fn_sig_for_diagnostic,
|
||||
intercrate,
|
||||
} = *self;
|
||||
InferCtxt {
|
||||
tcx,
|
||||
@ -641,6 +670,7 @@ pub fn build(&mut self) -> InferCtxt<'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::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 @@ fn push_outlives(
|
||||
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 @@ fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<
|
||||
.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 @@ fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
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 @@ fn a_is_expected(&self) -> bool {
|
||||
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 @@ fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
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 @@ fn a_is_expected(&self) -> bool {
|
||||
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 @@ fn a_is_expected(&self) -> bool {
|
||||
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 @@ fn a_is_expected(&self) -> bool {
|
||||
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 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
|
||||
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||
// Nothing to elaborate
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1659,6 +1659,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||
Coerce(..) |
|
||||
ConstEvaluatable(..) |
|
||||
ConstEquate(..) |
|
||||
Ambiguous |
|
||||
TypeWellFormedFromEnv(..) => continue,
|
||||
};
|
||||
if predicate.is_global() {
|
||||
|
@ -36,6 +36,11 @@ fn tag(&self) -> &'static str {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn intercrate(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
@ -43,6 +48,10 @@ fn a_is_expected(&self) -> bool {
|
||||
true
|
||||
} // irrelevant
|
||||
|
||||
fn mark_ambiguous(&mut self) {
|
||||
bug!()
|
||||
}
|
||||
|
||||
fn relate_with_variance<T: Relate<'tcx>>(
|
||||
&mut self,
|
||||
_: ty::Variance,
|
||||
|
@ -42,7 +42,6 @@ pub enum SimplifiedTypeGen<D>
|
||||
ClosureSimplifiedType(D),
|
||||
GeneratorSimplifiedType(D),
|
||||
GeneratorWitnessSimplifiedType(usize),
|
||||
OpaqueSimplifiedType(D),
|
||||
FunctionSimplifiedType(usize),
|
||||
PlaceholderSimplifiedType,
|
||||
}
|
||||
@ -127,7 +126,7 @@ pub fn simplify_type<'tcx>(
|
||||
TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
|
||||
TreatParams::AsInfer => None,
|
||||
},
|
||||
ty::Projection(_) => match treat_params {
|
||||
ty::Opaque(..) | ty::Projection(_) => match treat_params {
|
||||
// When treating `ty::Param` as a placeholder, projections also
|
||||
// don't unify with anything else as long as they are fully normalized.
|
||||
//
|
||||
@ -138,7 +137,6 @@ pub fn simplify_type<'tcx>(
|
||||
}
|
||||
TreatParams::AsPlaceholder | TreatParams::AsInfer => None,
|
||||
},
|
||||
ty::Opaque(def_id, _) => Some(OpaqueSimplifiedType(def_id)),
|
||||
ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
|
||||
ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
|
||||
}
|
||||
@ -151,8 +149,7 @@ pub fn def(self) -> Option<D> {
|
||||
| ForeignSimplifiedType(d)
|
||||
| TraitSimplifiedType(d)
|
||||
| ClosureSimplifiedType(d)
|
||||
| GeneratorSimplifiedType(d)
|
||||
| OpaqueSimplifiedType(d) => Some(d),
|
||||
| GeneratorSimplifiedType(d) => Some(d),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -182,7 +179,6 @@ pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
|
||||
ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
|
||||
GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
|
||||
GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
|
||||
OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)),
|
||||
FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
|
||||
PlaceholderSimplifiedType => PlaceholderSimplifiedType,
|
||||
}
|
||||
@ -229,7 +225,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
|
||||
match impl_ty.kind() {
|
||||
// Start by checking whether the type in the impl may unify with
|
||||
// pretty much everything. Just return `true` in that case.
|
||||
ty::Param(_) | ty::Projection(_) | ty::Error(_) => return true,
|
||||
ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
|
||||
// These types only unify with inference variables or their own
|
||||
// variant.
|
||||
ty::Bool
|
||||
@ -247,8 +243,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
|
||||
| ty::Never
|
||||
| ty::Tuple(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Opaque(..) => {}
|
||||
| ty::Foreign(..) => {}
|
||||
ty::FnDef(..)
|
||||
| ty::Closure(..)
|
||||
| ty::Generator(..)
|
||||
@ -328,10 +323,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
|
||||
_ => false,
|
||||
},
|
||||
|
||||
// Opaque types in impls should be forbidden, but that doesn't
|
||||
// stop compilation. So this match arm should never return true
|
||||
// if compilation succeeds.
|
||||
ty::Opaque(..) => matches!(k, ty::Opaque(..)),
|
||||
ty::Opaque(..) => true,
|
||||
|
||||
// Impls cannot contain these types as these cannot be named directly.
|
||||
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
|
||||
|
@ -259,6 +259,7 @@ fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
|
||||
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
|
||||
self.add_ty(ty);
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,6 +620,7 @@ pub fn allow_normalization(self) -> bool {
|
||||
| PredicateKind::Coerce(_)
|
||||
| PredicateKind::ConstEvaluatable(_)
|
||||
| PredicateKind::ConstEquate(_, _)
|
||||
| PredicateKind::Ambiguous
|
||||
| PredicateKind::TypeWellFormedFromEnv(_) => true,
|
||||
}
|
||||
}
|
||||
@ -702,6 +703,10 @@ pub enum PredicateKind<'tcx> {
|
||||
///
|
||||
/// Only used for Chalk.
|
||||
TypeWellFormedFromEnv(Ty<'tcx>),
|
||||
|
||||
/// A marker predicate that is always ambiguous.
|
||||
/// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
|
||||
Ambiguous,
|
||||
}
|
||||
|
||||
/// The crate outlives map is computed during typeck and contains the
|
||||
@ -1186,6 +1191,7 @@ pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
|
||||
| PredicateKind::TypeOutlives(..)
|
||||
| PredicateKind::ConstEvaluatable(..)
|
||||
| PredicateKind::ConstEquate(..)
|
||||
| PredicateKind::Ambiguous
|
||||
| PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
}
|
||||
}
|
||||
@ -1204,6 +1210,7 @@ pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>
|
||||
| PredicateKind::TypeOutlives(..)
|
||||
| PredicateKind::ConstEvaluatable(..)
|
||||
| PredicateKind::ConstEquate(..)
|
||||
| PredicateKind::Ambiguous
|
||||
| PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
}
|
||||
}
|
||||
@ -1222,6 +1229,7 @@ pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
|
||||
| PredicateKind::ClosureKind(..)
|
||||
| PredicateKind::ConstEvaluatable(..)
|
||||
| PredicateKind::ConstEquate(..)
|
||||
| PredicateKind::Ambiguous
|
||||
| PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
}
|
||||
}
|
||||
|
@ -2704,6 +2704,7 @@ pub struct PrintClosureAsImpl<'tcx> {
|
||||
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
|
||||
p!("the type `", print(ty), "` is found in the environment")
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => p!("ambiguous"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@ pub enum Cause {
|
||||
pub trait TypeRelation<'tcx>: Sized {
|
||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||
|
||||
fn intercrate(&self) -> bool;
|
||||
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx>;
|
||||
|
||||
/// Returns a static string we can use for printouts.
|
||||
@ -32,6 +34,9 @@ pub trait TypeRelation<'tcx>: Sized {
|
||||
/// relation. Just affects error messages.
|
||||
fn a_is_expected(&self) -> bool;
|
||||
|
||||
/// Used during coherence. If called, must emit an always-ambiguous obligation.
|
||||
fn mark_ambiguous(&mut self);
|
||||
|
||||
fn with_cause<F, R>(&mut self, _cause: Cause, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
@ -562,16 +567,23 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||
(&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
|
||||
if a_def_id == b_def_id =>
|
||||
{
|
||||
let opt_variances = tcx.variances_of(a_def_id);
|
||||
let substs = relate_substs_with_variances(
|
||||
relation,
|
||||
a_def_id,
|
||||
opt_variances,
|
||||
a_substs,
|
||||
b_substs,
|
||||
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
|
||||
)?;
|
||||
Ok(tcx.mk_opaque(a_def_id, substs))
|
||||
if relation.intercrate() {
|
||||
// During coherence, opaque types should be treated as equal to each other, even if their generic params
|
||||
// differ, as they could resolve to the same hidden type, even for different generic params.
|
||||
relation.mark_ambiguous();
|
||||
Ok(a)
|
||||
} else {
|
||||
let opt_variances = tcx.variances_of(a_def_id);
|
||||
let substs = relate_substs_with_variances(
|
||||
relation,
|
||||
a_def_id,
|
||||
opt_variances,
|
||||
a_substs,
|
||||
b_substs,
|
||||
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
|
||||
)?;
|
||||
Ok(tcx.mk_opaque(a_def_id, substs))
|
||||
}
|
||||
}
|
||||
|
||||
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),
|
||||
|
@ -173,6 +173,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
|
||||
write!(f, "TypeWellFormedFromEnv({:?})", ty)
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -841,6 +841,7 @@ fn evaluate_nested_obligations(
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
|
||||
ty::PredicateKind::Ambiguous => return false,
|
||||
};
|
||||
}
|
||||
true
|
||||
|
@ -18,7 +18,7 @@
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::traits::specialization_graph::OverlapMode;
|
||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
||||
@ -94,8 +94,9 @@ pub fn overlapping_impls<'tcx>(
|
||||
return None;
|
||||
}
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let selcx = &mut SelectionContext::intercrate(&infcx);
|
||||
let infcx =
|
||||
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build();
|
||||
let selcx = &mut SelectionContext::new(&infcx);
|
||||
let overlaps =
|
||||
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
|
||||
if !overlaps {
|
||||
@ -105,8 +106,9 @@ pub fn overlapping_impls<'tcx>(
|
||||
// In the case where we detect an error, run the check again, but
|
||||
// this time tracking intercrate ambiguity causes for better
|
||||
// diagnostics. (These take time and can lead to false errors.)
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let selcx = &mut SelectionContext::intercrate(&infcx);
|
||||
let infcx =
|
||||
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build();
|
||||
let selcx = &mut SelectionContext::new(&infcx);
|
||||
selcx.enable_tracking_intercrate_ambiguity_causes();
|
||||
Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())
|
||||
}
|
||||
|
@ -1168,6 +1168,8 @@ fn report_selection_error(
|
||||
)
|
||||
}
|
||||
|
||||
ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
|
||||
|
||||
ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!(
|
||||
span,
|
||||
"TypeWellFormedFromEnv predicate should only exist in the environment"
|
||||
|
@ -336,6 +336,7 @@ fn process_obligation(
|
||||
ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
|
||||
ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
|
||||
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||
bug!("TypeWellFormedFromEnv is only used for Chalk")
|
||||
}
|
||||
@ -569,6 +570,7 @@ fn process_obligation(
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
|
||||
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||
bug!("TypeWellFormedFromEnv is only used for Chalk")
|
||||
}
|
||||
|
@ -319,6 +319,7 @@ fn predicate_references_self<'tcx>(
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
}
|
||||
}
|
||||
@ -350,6 +351,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
| ty::PredicateKind::TypeOutlives(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
|
||||
}
|
||||
})
|
||||
|
@ -110,25 +110,6 @@ pub struct SelectionContext<'cx, 'tcx> {
|
||||
/// require themselves.
|
||||
freshener: TypeFreshener<'cx, '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.
|
||||
intercrate: bool,
|
||||
/// If `intercrate` is set, we remember predicates which were
|
||||
/// considered ambiguous because of impls potentially added in other crates.
|
||||
/// This is used in coherence to give improved diagnostics.
|
||||
@ -226,16 +207,11 @@ pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
|
||||
SelectionContext {
|
||||
infcx,
|
||||
freshener: infcx.freshener_keep_static(),
|
||||
intercrate: false,
|
||||
intercrate_ambiguity_causes: None,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intercrate(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
|
||||
SelectionContext { intercrate: true, ..SelectionContext::new(infcx) }
|
||||
}
|
||||
|
||||
pub fn with_query_mode(
|
||||
infcx: &'cx InferCtxt<'tcx>,
|
||||
query_mode: TraitQueryMode,
|
||||
@ -247,7 +223,7 @@ pub fn with_query_mode(
|
||||
/// Enables tracking of intercrate ambiguity causes. See
|
||||
/// the documentation of [`Self::intercrate_ambiguity_causes`] for more.
|
||||
pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
|
||||
assert!(self.intercrate);
|
||||
assert!(self.is_intercrate());
|
||||
assert!(self.intercrate_ambiguity_causes.is_none());
|
||||
self.intercrate_ambiguity_causes = Some(FxIndexSet::default());
|
||||
debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
|
||||
@ -257,7 +233,7 @@ pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
|
||||
/// was enabled and disables tracking at the same time. If
|
||||
/// tracking is not enabled, just returns an empty vector.
|
||||
pub fn take_intercrate_ambiguity_causes(&mut self) -> FxIndexSet<IntercrateAmbiguityCause> {
|
||||
assert!(self.intercrate);
|
||||
assert!(self.is_intercrate());
|
||||
self.intercrate_ambiguity_causes.take().unwrap_or_default()
|
||||
}
|
||||
|
||||
@ -270,7 +246,7 @@ pub fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
}
|
||||
|
||||
pub fn is_intercrate(&self) -> bool {
|
||||
self.intercrate
|
||||
self.infcx.intercrate
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -741,6 +717,7 @@ fn evaluate_predicate_recursively<'o>(
|
||||
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||
bug!("TypeWellFormedFromEnv is only used for chalk")
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -751,7 +728,7 @@ fn evaluate_trait_predicate_recursively<'o>(
|
||||
previous_stack: TraitObligationStackList<'o, 'tcx>,
|
||||
mut obligation: TraitObligation<'tcx>,
|
||||
) -> Result<EvaluationResult, OverflowError> {
|
||||
if !self.intercrate
|
||||
if !self.is_intercrate()
|
||||
&& obligation.is_global()
|
||||
&& obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst())
|
||||
{
|
||||
@ -1014,7 +991,7 @@ fn check_evaluation_cache(
|
||||
// mode, so don't do any caching. In particular, we might
|
||||
// re-use the same `InferCtxt` with both an intercrate
|
||||
// and non-intercrate `SelectionContext`
|
||||
if self.intercrate {
|
||||
if self.is_intercrate() {
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -1044,7 +1021,7 @@ fn insert_evaluation_cache(
|
||||
// mode, so don't do any caching. In particular, we might
|
||||
// re-use the same `InferCtxt` with both an intercrate
|
||||
// and non-intercrate `SelectionContext`
|
||||
if self.intercrate {
|
||||
if self.is_intercrate() {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1225,9 +1202,9 @@ fn filter_reservation_impls(
|
||||
}
|
||||
|
||||
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
|
||||
debug!("is_knowable(intercrate={:?})", self.intercrate);
|
||||
debug!("is_knowable(intercrate={:?})", self.is_intercrate());
|
||||
|
||||
if !self.intercrate || stack.obligation.polarity() == ty::ImplPolarity::Negative {
|
||||
if !self.is_intercrate() || stack.obligation.polarity() == ty::ImplPolarity::Negative {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -1258,7 +1235,7 @@ fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||
// the master cache. Since coherence executes pretty quickly,
|
||||
// it's not worth going to more trouble to increase the
|
||||
// hit-rate, I don't think.
|
||||
if self.intercrate {
|
||||
if self.is_intercrate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1275,7 +1252,7 @@ fn check_candidate_cache(
|
||||
// mode, so don't do any caching. In particular, we might
|
||||
// re-use the same `InferCtxt` with both an intercrate
|
||||
// and non-intercrate `SelectionContext`
|
||||
if self.intercrate {
|
||||
if self.is_intercrate() {
|
||||
return None;
|
||||
}
|
||||
let tcx = self.tcx();
|
||||
@ -1314,7 +1291,7 @@ fn can_cache_candidate(
|
||||
// mode, so don't do any caching. In particular, we might
|
||||
// re-use the same `InferCtxt` with both an intercrate
|
||||
// and non-intercrate `SelectionContext`
|
||||
if self.intercrate {
|
||||
if self.is_intercrate() {
|
||||
return false;
|
||||
}
|
||||
match result {
|
||||
@ -2191,7 +2168,7 @@ fn match_impl(
|
||||
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{e}`"))?;
|
||||
nested_obligations.extend(obligations);
|
||||
|
||||
if !self.intercrate
|
||||
if !self.is_intercrate()
|
||||
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
|
||||
{
|
||||
debug!("reservation impls only apply in intercrate mode");
|
||||
|
@ -155,6 +155,7 @@ pub fn predicate_obligations<'tcx>(
|
||||
wf.compute(c1.into());
|
||||
wf.compute(c2.into());
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => {}
|
||||
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||
bug!("TypeWellFormedFromEnv is only used for Chalk")
|
||||
}
|
||||
@ -875,6 +876,7 @@ pub(crate) fn required_region_bounds<'tcx>(
|
||||
| ty::PredicateKind::RegionOutlives(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
|
||||
// Search for a bound of the form `erased_self_ty
|
||||
|
@ -121,6 +121,7 @@ fn lower_into(
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
|
||||
};
|
||||
let value = chalk_ir::ProgramClauseImplication {
|
||||
@ -212,6 +213,7 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::GoalData<RustInte
|
||||
ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::ConstEquate(..) => {
|
||||
chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
|
||||
}
|
||||
@ -625,6 +627,7 @@ fn lower_into(
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||
bug!("unexpected predicate {}", &self)
|
||||
}
|
||||
@ -754,6 +757,7 @@ fn lower_into(
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||
bug!("unexpected predicate {}", &self)
|
||||
}
|
||||
|
@ -97,6 +97,7 @@ fn compute_implied_outlives_bounds<'tcx>(
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
ty::PredicateKind::WellFormed(arg) => {
|
||||
wf_args.push(arg);
|
||||
|
@ -66,6 +66,7 @@ fn not_outlives_predicate<'tcx>(p: ty::Predicate<'tcx>) -> bool {
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => true,
|
||||
}
|
||||
}
|
||||
|
@ -318,6 +318,7 @@ pub(crate) fn clean_predicate<'tcx>(
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ fn defining_use() -> OpaqueClosure {
|
||||
struct Wrapper<T>(T);
|
||||
trait Trait {}
|
||||
impl Trait for Wrapper<OpaqueClosure> {}
|
||||
//~^ ERROR cannot implement trait on type alias impl trait
|
||||
impl<T: Sync> Trait for Wrapper<T> {}
|
||||
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
|
||||
|
||||
|
@ -1,24 +1,11 @@
|
||||
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
|
||||
--> $DIR/coherence-with-closure.rs:12:1
|
||||
--> $DIR/coherence-with-closure.rs:11:1
|
||||
|
|
||||
LL | impl Trait for Wrapper<OpaqueClosure> {}
|
||||
| ------------------------------------- first implementation here
|
||||
LL |
|
||||
LL | impl<T: Sync> Trait for Wrapper<T> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
|
||||
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/coherence-with-closure.rs:10:24
|
||||
|
|
||||
LL | impl Trait for Wrapper<OpaqueClosure> {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/coherence-with-closure.rs:3:22
|
||||
|
|
||||
LL | type OpaqueClosure = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
|
@ -12,7 +12,6 @@ fn defining_use() -> OpaqueGenerator {
|
||||
struct Wrapper<T>(T);
|
||||
trait Trait {}
|
||||
impl Trait for Wrapper<OpaqueGenerator> {}
|
||||
//~^ ERROR cannot implement trait on type alias impl trait
|
||||
impl<T: Sync> Trait for Wrapper<T> {}
|
||||
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
|
||||
|
||||
|
@ -1,24 +1,11 @@
|
||||
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
|
||||
--> $DIR/coherence-with-generator.rs:16:1
|
||||
--> $DIR/coherence-with-generator.rs:15:1
|
||||
|
|
||||
LL | impl Trait for Wrapper<OpaqueGenerator> {}
|
||||
| --------------------------------------- first implementation here
|
||||
LL |
|
||||
LL | impl<T: Sync> Trait for Wrapper<T> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
|
||||
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/coherence-with-generator.rs:14:24
|
||||
|
|
||||
LL | impl Trait for Wrapper<OpaqueGenerator> {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/coherence-with-generator.rs:3:24
|
||||
|
|
||||
LL | type OpaqueGenerator = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
|
@ -20,7 +20,6 @@ impl<T: Send> AnotherTrait for T {}
|
||||
// in the future.)
|
||||
impl AnotherTrait for D<OpaqueType> {
|
||||
//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
|
||||
//~| ERROR cannot implement trait on type alias impl trait
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -7,18 +7,6 @@ LL | impl<T: Send> AnotherTrait for T {}
|
||||
LL | impl AnotherTrait for D<OpaqueType> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
|
||||
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/auto-trait.rs:21:25
|
||||
|
|
||||
LL | impl AnotherTrait for D<OpaqueType> {
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/auto-trait.rs:7:19
|
||||
|
|
||||
LL | type OpaqueType = impl OpaqueTrait;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
|
@ -18,7 +18,6 @@ impl<T: std::fmt::Debug> AnotherTrait for T {}
|
||||
// This is in error, because we cannot assume that `OpaqueType: !Debug`
|
||||
impl AnotherTrait for D<OpaqueType> {
|
||||
//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
|
||||
//~| ERROR cannot implement trait on type alias impl trait
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -9,18 +9,6 @@ LL | impl AnotherTrait for D<OpaqueType> {
|
||||
|
|
||||
= note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
|
||||
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/negative-reasoning.rs:19:25
|
||||
|
|
||||
LL | impl AnotherTrait for D<OpaqueType> {
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/negative-reasoning.rs:7:19
|
||||
|
|
||||
LL | type OpaqueType = impl OpaqueTrait;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
|
@ -5,13 +5,13 @@
|
||||
struct Bar;
|
||||
|
||||
impl PartialEq<(Foo, i32)> for Bar {
|
||||
//~^ ERROR cannot implement trait on type alias impl trait
|
||||
fn eq(&self, _other: &(Foo, i32)) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn foo() -> Foo {
|
||||
//~^ ERROR can't compare `Bar` with `(Bar, i32)`
|
||||
Bar
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:7:17
|
||||
error[E0277]: can't compare `Bar` with `(Bar, i32)`
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:13:13
|
||||
|
|
||||
LL | impl PartialEq<(Foo, i32)> for Bar {
|
||||
| ^^^
|
||||
LL | fn foo() -> Foo {
|
||||
| ^^^ no implementation for `Bar == (Bar, i32)`
|
||||
LL |
|
||||
LL | Bar
|
||||
| --- return type was inferred to be `Bar` here
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:3:12
|
||||
|
|
||||
LL | type Foo = impl PartialEq<(Foo, i32)>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar`
|
||||
= help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -2,11 +2,13 @@
|
||||
|
||||
mod a {
|
||||
type Foo = impl PartialEq<(Foo, i32)>;
|
||||
//~^ ERROR: unconstrained opaque type
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl PartialEq<(Bar, i32)> for Bar {
|
||||
fn eq(&self, _other: &(Foo, i32)) -> bool {
|
||||
//~^ ERROR: `eq` has an incompatible type for trait
|
||||
true
|
||||
}
|
||||
}
|
||||
@ -14,12 +16,13 @@ fn eq(&self, _other: &(Foo, i32)) -> bool {
|
||||
|
||||
mod b {
|
||||
type Foo = impl PartialEq<(Foo, i32)>;
|
||||
//~^ ERROR: unconstrained opaque type
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl PartialEq<(Foo, i32)> for Bar {
|
||||
//~^ ERROR cannot implement trait on type alias impl trait
|
||||
fn eq(&self, _other: &(Bar, i32)) -> bool {
|
||||
//~^ ERROR: `eq` has an incompatible type for trait
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,49 @@
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:20:21
|
||||
|
|
||||
LL | impl PartialEq<(Foo, i32)> for Bar {
|
||||
| ^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:16:16
|
||||
error: unconstrained opaque type
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16
|
||||
|
|
||||
LL | type Foo = impl PartialEq<(Foo, i32)>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `Foo` must be used in combination with a concrete type within the same module
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0053]: method `eq` has an incompatible type for trait
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:30
|
||||
|
|
||||
LL | type Foo = impl PartialEq<(Foo, i32)>;
|
||||
| -------------------------- the found opaque type
|
||||
...
|
||||
LL | fn eq(&self, _other: &(Foo, i32)) -> bool {
|
||||
| ^^^^^^^^^^^
|
||||
| |
|
||||
| expected struct `a::Bar`, found opaque type
|
||||
| help: change the parameter type to match the trait: `&(a::Bar, i32)`
|
||||
|
|
||||
= note: expected fn pointer `fn(&a::Bar, &(a::Bar, i32)) -> _`
|
||||
found fn pointer `fn(&a::Bar, &(a::Foo, i32)) -> _`
|
||||
|
||||
error: unconstrained opaque type
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
|
||||
|
|
||||
LL | type Foo = impl PartialEq<(Foo, i32)>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `Foo` must be used in combination with a concrete type within the same module
|
||||
|
||||
error[E0053]: method `eq` has an incompatible type for trait
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:30
|
||||
|
|
||||
LL | type Foo = impl PartialEq<(Foo, i32)>;
|
||||
| -------------------------- the expected opaque type
|
||||
...
|
||||
LL | fn eq(&self, _other: &(Bar, i32)) -> bool {
|
||||
| ^^^^^^^^^^^
|
||||
| |
|
||||
| expected opaque type, found struct `b::Bar`
|
||||
| help: change the parameter type to match the trait: `&(b::Foo, i32)`
|
||||
|
|
||||
= note: expected fn pointer `fn(&b::Bar, &(b::Foo, i32)) -> _`
|
||||
found fn pointer `fn(&b::Bar, &(b::Bar, i32)) -> _`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0053`.
|
||||
|
@ -9,5 +9,4 @@ trait AnotherTrait {}
|
||||
impl<T: Send> AnotherTrait for T {}
|
||||
impl AnotherTrait for OpaqueType {}
|
||||
//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
|
||||
//~| ERROR cannot implement trait on type alias impl trait
|
||||
fn main() {}
|
||||
|
@ -6,18 +6,6 @@ LL | impl<T: Send> AnotherTrait for T {}
|
||||
LL | impl AnotherTrait for OpaqueType {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
|
||||
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/issue-83613.rs:10:23
|
||||
|
|
||||
LL | impl AnotherTrait for OpaqueType {}
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/issue-83613.rs:4:19
|
||||
|
|
||||
LL | type OpaqueType = impl OpaqueTrait;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
|
@ -12,6 +12,6 @@ fn use_alias<T>(val: T) -> AliasOfForeignType<T> {
|
||||
}
|
||||
|
||||
impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
|
||||
//~^ ERROR cannot implement trait on type alias impl trait
|
||||
//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,14 +1,14 @@
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/coherence.rs:14:41
|
||||
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
|
||||
--> $DIR/coherence.rs:14:1
|
||||
|
|
||||
LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------
|
||||
| | |
|
||||
| | `AliasOfForeignType<T>` is not defined in the current crate
|
||||
| impl doesn't use only types from inside the current crate
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/coherence.rs:9:30
|
||||
|
|
||||
LL | type AliasOfForeignType<T> = impl LocalTrait;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= note: define and implement a trait or new type instead
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0117`.
|
||||
|
@ -0,0 +1,13 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
trait Trait {}
|
||||
type Opaque<T> = impl Sized;
|
||||
fn foo<T>() -> Opaque<T> {
|
||||
()
|
||||
}
|
||||
|
||||
impl<T, V> Trait for (T, V, V, u32) {}
|
||||
impl<U, V> Trait for (Opaque<U>, V, i32, V) {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,23 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
trait Foo {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl Foo for i32 {
|
||||
type Assoc = u32;
|
||||
}
|
||||
type ImplTrait = impl Sized;
|
||||
fn constrain() -> ImplTrait {
|
||||
1u64
|
||||
}
|
||||
impl Foo for i64 {
|
||||
type Assoc = ImplTrait;
|
||||
}
|
||||
|
||||
trait Bar<T> {}
|
||||
|
||||
impl<T: Foo> Bar<<T as Foo>::Assoc> for T {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,33 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Foo {}
|
||||
impl Foo for () {}
|
||||
impl Foo for i32 {}
|
||||
|
||||
type Bar<T: Foo> = impl std::fmt::Debug;
|
||||
fn defining_use<T: Foo>() -> Bar<T> {
|
||||
42
|
||||
}
|
||||
|
||||
trait Bop {}
|
||||
|
||||
impl Bop for Bar<()> {}
|
||||
|
||||
// If the hidden type is the same, this is effectively a second impl for the same type.
|
||||
impl Bop for Bar<i32> {}
|
||||
//~^ ERROR conflicting implementations
|
||||
|
||||
type Barr = impl std::fmt::Debug;
|
||||
fn defining_use2() -> Barr {
|
||||
42
|
||||
}
|
||||
|
||||
// Even completely different opaque types must conflict.
|
||||
impl Bop for Barr {}
|
||||
//~^ ERROR conflicting implementations
|
||||
|
||||
// And obviously the hidden type must conflict, too.
|
||||
impl Bop for i32 {}
|
||||
//~^ ERROR conflicting implementations
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,30 @@
|
||||
error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
|
||||
--> $DIR/impl_trait_for_same_tait.rs:17:1
|
||||
|
|
||||
LL | impl Bop for Bar<()> {}
|
||||
| -------------------- first implementation here
|
||||
...
|
||||
LL | impl Bop for Bar<i32> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
|
||||
|
||||
error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
|
||||
--> $DIR/impl_trait_for_same_tait.rs:26:1
|
||||
|
|
||||
LL | impl Bop for Bar<()> {}
|
||||
| -------------------- first implementation here
|
||||
...
|
||||
LL | impl Bop for Barr {}
|
||||
| ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
|
||||
|
||||
error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
|
||||
--> $DIR/impl_trait_for_same_tait.rs:30:1
|
||||
|
|
||||
LL | impl Bop for Bar<()> {}
|
||||
| -------------------- first implementation here
|
||||
...
|
||||
LL | impl Bop for i32 {}
|
||||
| ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
21
src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs
Normal file
21
src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// compile-flags: --crate-type=lib
|
||||
// check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
type Alias = impl Sized;
|
||||
|
||||
fn constrain() -> Alias {
|
||||
1i32
|
||||
}
|
||||
|
||||
trait HideIt {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl HideIt for () {
|
||||
type Assoc = Alias;
|
||||
}
|
||||
|
||||
pub trait Yay {}
|
||||
|
||||
impl Yay for <() as HideIt>::Assoc {}
|
@ -0,0 +1,19 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
type Foo = impl Debug;
|
||||
pub trait Yay { }
|
||||
impl Yay for Foo { }
|
||||
|
||||
fn foo() {
|
||||
is_yay::<u32>(); //~ ERROR: the trait bound `u32: Yay` is not satisfied
|
||||
is_debug::<u32>(); // OK
|
||||
is_yay::<Foo>(); // OK
|
||||
is_debug::<Foo>(); // OK
|
||||
}
|
||||
|
||||
fn is_yay<T: Yay>() { }
|
||||
fn is_debug<T: Debug>() { }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,16 @@
|
||||
error[E0277]: the trait bound `u32: Yay` is not satisfied
|
||||
--> $DIR/impl_trait_for_tait_bound.rs:10:14
|
||||
|
|
||||
LL | is_yay::<u32>();
|
||||
| ^^^ the trait `Yay` is not implemented for `u32`
|
||||
|
|
||||
= help: the trait `Yay` is implemented for `Foo`
|
||||
note: required by a bound in `is_yay`
|
||||
--> $DIR/impl_trait_for_tait_bound.rs:16:14
|
||||
|
|
||||
LL | fn is_yay<T: Yay>() { }
|
||||
| ^^^ required by this bound in `is_yay`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,16 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
type Foo = impl Debug;
|
||||
|
||||
pub trait Yay { }
|
||||
impl Yay for u32 { }
|
||||
|
||||
fn foo() {
|
||||
is_yay::<Foo>(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied
|
||||
}
|
||||
|
||||
fn is_yay<T: Yay>() { }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,16 @@
|
||||
error[E0277]: the trait bound `Foo: Yay` is not satisfied
|
||||
--> $DIR/impl_trait_for_tait_bound2.rs:11:14
|
||||
|
|
||||
LL | is_yay::<Foo>();
|
||||
| ^^^ the trait `Yay` is not implemented for `Foo`
|
||||
|
|
||||
= help: the trait `Yay` is implemented for `u32`
|
||||
note: required by a bound in `is_yay`
|
||||
--> $DIR/impl_trait_for_tait_bound2.rs:14:14
|
||||
|
|
||||
LL | fn is_yay<T: Yay>() { }
|
||||
| ^^^ required by this bound in `is_yay`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -8,7 +8,7 @@ impl MyTrait for () {}
|
||||
type Bar = impl MyTrait;
|
||||
|
||||
impl MyTrait for Bar {}
|
||||
//~^ ERROR: cannot implement trait on type alias impl trait
|
||||
//~^ ERROR: conflicting implementations of trait `MyTrait` for type `()`
|
||||
|
||||
fn bazr() -> Bar { }
|
||||
|
||||
|
@ -1,14 +1,12 @@
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/issue-65384.rs:10:18
|
||||
error[E0119]: conflicting implementations of trait `MyTrait` for type `()`
|
||||
--> $DIR/issue-65384.rs:10:1
|
||||
|
|
||||
LL | impl MyTrait for () {}
|
||||
| ------------------- first implementation here
|
||||
...
|
||||
LL | impl MyTrait for Bar {}
|
||||
| ^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/issue-65384.rs:8:12
|
||||
|
|
||||
LL | type Bar = impl MyTrait;
|
||||
| ^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Regression test for issue #76202
|
||||
// Tests that we don't ICE when we have a trait impl on a TAIT.
|
||||
|
||||
// check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Dummy {}
|
||||
@ -14,7 +16,12 @@ trait Test {
|
||||
}
|
||||
|
||||
impl Test for F {
|
||||
//~^ ERROR cannot implement trait
|
||||
fn test(self) {}
|
||||
}
|
||||
|
||||
// Ok because `i32` does not implement `Dummy`,
|
||||
// so it can't possibly be the hidden type of `F`.
|
||||
impl Test for i32 {
|
||||
fn test(self) {}
|
||||
}
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/issue-76202-trait-impl-for-tait.rs:16:15
|
||||
|
|
||||
LL | impl Test for F {
|
||||
| ^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/issue-76202-trait-impl-for-tait.rs:9:10
|
||||
|
|
||||
LL | type F = impl Dummy;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Regression test for issues #84660 and #86411: both are variations on #76202.
|
||||
// Tests that we don't ICE when we have an opaque type appearing anywhere in an impl header.
|
||||
|
||||
// check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Foo {}
|
||||
@ -12,7 +14,7 @@ trait TraitArg<T> {
|
||||
fn f();
|
||||
}
|
||||
|
||||
impl TraitArg<Bar> for () { //~ ERROR cannot implement trait
|
||||
impl TraitArg<Bar> for () {
|
||||
fn f() {
|
||||
println!("ho");
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/issue-84660-trait-impl-for-tait.rs:15:15
|
||||
|
|
||||
LL | impl TraitArg<Bar> for () {
|
||||
| ^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/issue-84660-trait-impl-for-tait.rs:8:12
|
||||
|
|
||||
LL | type Bar = impl Foo;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -13,14 +13,14 @@ trait Trait<T, In> {
|
||||
fn convert(i: In) -> Self::Out;
|
||||
}
|
||||
|
||||
impl<In, Out> Trait<Bar, In> for Out { //~ ERROR cannot implement trait
|
||||
impl<In, Out> Trait<Bar, In> for Out {
|
||||
type Out = Out;
|
||||
fn convert(_i: In) -> Self::Out {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
impl<In, Out> Trait<(), In> for Out {
|
||||
impl<In, Out> Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait<Bar, _>`
|
||||
type Out = In;
|
||||
fn convert(i: In) -> Self::Out {
|
||||
i
|
||||
|
@ -1,14 +1,12 @@
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/issue-84660-unsoundness.rs:16:21
|
||||
error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
|
||||
--> $DIR/issue-84660-unsoundness.rs:23:1
|
||||
|
|
||||
LL | impl<In, Out> Trait<Bar, In> for Out {
|
||||
| ^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/issue-84660-unsoundness.rs:8:12
|
||||
|
|
||||
LL | type Bar = impl Foo;
|
||||
| ^^^^^^^^
|
||||
| ------------------------------------ first implementation here
|
||||
...
|
||||
LL | impl<In, Out> Trait<(), In> for Out {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
|
@ -4,11 +4,11 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
type FooX = impl Debug;
|
||||
//~^ ERROR unconstrained opaque type
|
||||
|
||||
trait Foo<A> { }
|
||||
|
||||
impl Foo<FooX> for () { }
|
||||
//~^ cannot implement trait on type alias impl trait
|
||||
|
||||
fn foo() -> impl Foo<FooX> {
|
||||
()
|
||||
|
@ -1,14 +1,10 @@
|
||||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/nested-tait-inference3.rs:10:10
|
||||
|
|
||||
LL | impl Foo<FooX> for () { }
|
||||
| ^^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
error: unconstrained opaque type
|
||||
--> $DIR/nested-tait-inference3.rs:6:13
|
||||
|
|
||||
LL | type FooX = impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `FooX` must be used in combination with a concrete type within the same module
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -37,6 +37,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: Option<
|
||||
ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
|
||||
ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
|
||||
ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"),
|
||||
ty::PredicateKind::Ambiguous => panic!("ambiguous predicate on function: {predicate:#?}"),
|
||||
}
|
||||
}
|
||||
match predicates.parent {
|
||||
|
Loading…
Reference in New Issue
Block a user