diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 94d5103286609..b2702eafd33bd 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -2,9 +2,8 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRe 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 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '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. - fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {} - fn normalization() -> NormalizationStrategy { NormalizationStrategy::Eager } @@ -156,10 +148,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> 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 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> }, ) .unwrap(); - Ok(()) } } diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index a74016e220e62..e0b465bab16d9 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -244,6 +244,10 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> { self.tcx } + fn intercrate(&self) -> bool { + false + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } @@ -256,6 +260,10 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> { true } + fn mark_ambiguous(&mut self) { + bug!() + } + fn relate_with_variance>( &mut self, _: ty::Variance, diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 71c932d747bca..d66b6585fb6f7 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxHashSet; 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( diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 55cca0cd2d7b5..bae43138b4d52 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -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, } } diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 7534482cce9bb..f0381353551c2 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -59,6 +59,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => (), } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 38499907663e1..c7bfe99aa9a8a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -702,6 +702,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // code is looking for a self type of an unresolved // inference variable. | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, }, ) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 9d75ccad133dd..44c3edf06a883 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -803,6 +803,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } }); diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 5ff3779fa1438..2483ab724a4e3 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -81,6 +81,7 @@ impl<'tcx> InferCtxt<'tcx> { .normalize_fn_sig_for_diagnostic .as_ref() .map(|f| f.clone()), + intercrate: self.intercrate, } } } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 34f54328230f4..b4a427a5d419a 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -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(()) } } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index c2552561c42df..eec938cefbb70 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -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( &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>( &mut self, _variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 59728148a84c4..8682f4d3b7aed 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -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, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 613a05e415ff9..0dee3be705474 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -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>( &mut self, _variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 6ffefcb7a286a..7f27b35a54e4f 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -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>( &mut self, variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index d6e56fcb7fd27..97ed4729bd0d9 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -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>( &mut self, variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b9ed6b28c220d..2798477d1815d 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -337,6 +337,26 @@ pub struct InferCtxt<'tcx> { normalize_fn_sig_for_diagnostic: Option, 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, 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, } } } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 167a82d4499a1..4f8460955c3de 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -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>, - ) -> Result<(), TypeError<'tcx>>; + fn register_obligations(&mut self, obligations: Vec>); /// 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>( &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>( &mut self, variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 2d19d1823fdfc..8f7805794513d 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -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)) diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index a5c21f0fb9b50..5d204dd70ed0c 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -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>( &mut self, _: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index bd3c5780b891b..2c6987cc3f456 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -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(&mut self, cause: Cause, f: F) -> R where F: FnOnce(&mut Self) -> R, diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index e12c069dcc1d9..b2a31ac7e6f1a 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -285,6 +285,7 @@ impl<'tcx> Elaborator<'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { // Nothing to elaborate } + ty::PredicateKind::Ambiguous => {} } } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8c779579a4f1d..ada3c3b67fb05 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1659,6 +1659,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { Coerce(..) | ConstEvaluatable(..) | ConstEquate(..) | + Ambiguous | TypeWellFormedFromEnv(..) => continue, }; if predicate.is_global() { diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index e6aab30a150de..cd147d7e55813 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -36,6 +36,11 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { 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 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { true } // irrelevant + fn mark_ambiguous(&mut self) { + bug!() + } + fn relate_with_variance>( &mut self, _: ty::Variance, diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 3be0bc4defc5c..1ee4985cf8de0 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -42,7 +42,6 @@ where 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 @@ impl SimplifiedTypeGen { | ForeignSimplifiedType(d) | TraitSimplifiedType(d) | ClosureSimplifiedType(d) - | GeneratorSimplifiedType(d) - | OpaqueSimplifiedType(d) => Some(d), + | GeneratorSimplifiedType(d) => Some(d), _ => None, } } @@ -182,7 +179,6 @@ impl SimplifiedTypeGen { 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 @@ impl DeepRejectCtxt { 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 @@ impl DeepRejectCtxt { | ty::Never | ty::Tuple(..) | ty::FnPtr(..) - | ty::Foreign(..) - | ty::Opaque(..) => {} + | ty::Foreign(..) => {} ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) @@ -328,10 +323,7 @@ impl DeepRejectCtxt { _ => 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, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 7201737be657b..ee4b8f91c5487 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -259,6 +259,7 @@ impl FlagComputation { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { self.add_ty(ty); } + ty::PredicateKind::Ambiguous => {} } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3f26d337d4575..0458c4abd3d4c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -620,6 +620,7 @@ impl<'tcx> Predicate<'tcx> { | 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 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeOutlives(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1204,6 +1210,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeOutlives(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1222,6 +1229,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ClosureKind(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index d828d08805ec3..ccfd4c96b13a6 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2703,6 +2703,7 @@ define_print_and_forward_display! { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { p!("the type `", print(ty), "` is found in the environment") } + ty::PredicateKind::Ambiguous => p!("ambiguous"), } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 0adc700586d9c..3d47b71b7ce62 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -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(&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))), diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 6be8fdd7cd795..64b4fd1176252 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -173,6 +173,7 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { write!(f, "TypeWellFormedFromEnv({:?})", ty) } + ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"), } } } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index a057e45ad6af4..78af187cd8f80 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -841,6 +841,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} + ty::PredicateKind::Ambiguous => return false, }; } true diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 1ef77e06b4874..741bf206d037e 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -18,7 +18,7 @@ use rustc_data_structures::fx::FxIndexSet; 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()) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 946e6e77a3da0..ef3d300020a39 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1168,6 +1168,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) } + ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"), + ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!( span, "TypeWellFormedFromEnv predicate should only exist in the environment" diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index d84f768cce4d7..d238e7556aea3 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -336,6 +336,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { 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 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } } + ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 90f48658113af..7c4c58ba36167 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -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, } }) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e54e290fb4b11..2803a2d38c807 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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 @@ impl<'cx, '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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// 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 { - assert!(self.intercrate); + assert!(self.is_intercrate()); self.intercrate_ambiguity_causes.take().unwrap_or_default() } @@ -270,7 +246,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } pub fn is_intercrate(&self) -> bool { - self.intercrate + self.infcx.intercrate } /////////////////////////////////////////////////////////////////////////// @@ -741,6 +717,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for chalk") } + ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), } }) } @@ -751,7 +728,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, mut obligation: TraitObligation<'tcx>, ) -> Result { - 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .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"); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 53783e1bc4b2c..5e506a23f383f 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -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 diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 06a42a95d6061..ee013515e86c4 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -121,6 +121,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment bug!("unexpected predicate {}", predicate), }; let value = chalk_ir::ProgramClauseImplication { @@ -212,6 +213,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi 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 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) } @@ -754,6 +757,7 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) } diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 82f6111f6f92e..2d1a386992617 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -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); diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index f1835d317e841..5200908527a16 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -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, } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7085bc8d1be55..b5d4ab55b4a83 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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"), } } diff --git a/src/test/ui/coherence/coherence-with-closure.rs b/src/test/ui/coherence/coherence-with-closure.rs index 6e3281d8508ab..5b6a62b24d4b3 100644 --- a/src/test/ui/coherence/coherence-with-closure.rs +++ b/src/test/ui/coherence/coherence-with-closure.rs @@ -8,7 +8,6 @@ fn defining_use() -> OpaqueClosure { struct Wrapper(T); trait Trait {} impl Trait for Wrapper {} -//~^ ERROR cannot implement trait on type alias impl trait impl Trait for Wrapper {} //~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper` diff --git a/src/test/ui/coherence/coherence-with-closure.stderr b/src/test/ui/coherence/coherence-with-closure.stderr index d2ca63fa14691..431108e14d7d8 100644 --- a/src/test/ui/coherence/coherence-with-closure.stderr +++ b/src/test/ui/coherence/coherence-with-closure.stderr @@ -1,24 +1,11 @@ error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper` - --> $DIR/coherence-with-closure.rs:12:1 + --> $DIR/coherence-with-closure.rs:11:1 | LL | impl Trait for Wrapper {} | ------------------------------------- first implementation here -LL | LL | impl Trait for Wrapper {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper` -error: cannot implement trait on type alias impl trait - --> $DIR/coherence-with-closure.rs:10:24 - | -LL | impl Trait for Wrapper {} - | ^^^^^^^^^^^^^ - | -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`. diff --git a/src/test/ui/coherence/coherence-with-generator.rs b/src/test/ui/coherence/coherence-with-generator.rs index d34c391db9fb0..70665ba06f954 100644 --- a/src/test/ui/coherence/coherence-with-generator.rs +++ b/src/test/ui/coherence/coherence-with-generator.rs @@ -12,7 +12,6 @@ fn defining_use() -> OpaqueGenerator { struct Wrapper(T); trait Trait {} impl Trait for Wrapper {} -//~^ ERROR cannot implement trait on type alias impl trait impl Trait for Wrapper {} //~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper` diff --git a/src/test/ui/coherence/coherence-with-generator.stderr b/src/test/ui/coherence/coherence-with-generator.stderr index 804bc1c3a6dd4..6d3be2e16c657 100644 --- a/src/test/ui/coherence/coherence-with-generator.stderr +++ b/src/test/ui/coherence/coherence-with-generator.stderr @@ -1,24 +1,11 @@ error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper` - --> $DIR/coherence-with-generator.rs:16:1 + --> $DIR/coherence-with-generator.rs:15:1 | LL | impl Trait for Wrapper {} | --------------------------------------- first implementation here -LL | LL | impl Trait for Wrapper {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper` -error: cannot implement trait on type alias impl trait - --> $DIR/coherence-with-generator.rs:14:24 - | -LL | impl Trait for Wrapper {} - | ^^^^^^^^^^^^^^^ - | -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`. diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs index afa95645a2786..35994e4a5ba3f 100644 --- a/src/test/ui/impl-trait/auto-trait.rs +++ b/src/test/ui/impl-trait/auto-trait.rs @@ -20,7 +20,6 @@ impl AnotherTrait for T {} // in the future.) impl AnotherTrait for D { //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` - //~| ERROR cannot implement trait on type alias impl trait } fn main() {} diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr index 5e10272b0db3c..81009413c9a26 100644 --- a/src/test/ui/impl-trait/auto-trait.stderr +++ b/src/test/ui/impl-trait/auto-trait.stderr @@ -7,18 +7,6 @@ LL | impl AnotherTrait for T {} LL | impl AnotherTrait for D { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` -error: cannot implement trait on type alias impl trait - --> $DIR/auto-trait.rs:21:25 - | -LL | impl AnotherTrait for D { - | ^^^^^^^^^^ - | -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`. diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs index da69bb349ae24..70e24a3a9d029 100644 --- a/src/test/ui/impl-trait/negative-reasoning.rs +++ b/src/test/ui/impl-trait/negative-reasoning.rs @@ -18,7 +18,6 @@ impl AnotherTrait for T {} // This is in error, because we cannot assume that `OpaqueType: !Debug` impl AnotherTrait for D { //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` - //~| ERROR cannot implement trait on type alias impl trait } fn main() {} diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr index 479b451855d55..6b8cc9e737423 100644 --- a/src/test/ui/impl-trait/negative-reasoning.stderr +++ b/src/test/ui/impl-trait/negative-reasoning.stderr @@ -9,18 +9,6 @@ LL | impl AnotherTrait for D { | = 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 { - | ^^^^^^^^^^ - | -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`. diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs index 621c4ea6e0d48..af9dfe25bb4ce 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs @@ -5,13 +5,13 @@ type Foo = impl PartialEq<(Foo, i32)>; 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 } diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr index 2ef1697ba341d..7b63a3d0b9f10 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr @@ -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`. diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs index df7966f00e172..91f1ed48133f5 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs @@ -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 @@ mod a { 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 } } diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index 6cd63dcf81c7f..3dda5761ada6b 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -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 +error: unconstrained opaque type + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16 | -LL | impl PartialEq<(Foo, i32)> for Bar { - | ^^^ +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: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: type alias impl trait defined here - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:16:16 + = 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 previous error +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/traits/alias/issue-83613.rs b/src/test/ui/traits/alias/issue-83613.rs index 04320e7207683..2462e703a7165 100644 --- a/src/test/ui/traits/alias/issue-83613.rs +++ b/src/test/ui/traits/alias/issue-83613.rs @@ -9,5 +9,4 @@ trait AnotherTrait {} impl 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() {} diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr index b9d93160192e9..a78294da6c140 100644 --- a/src/test/ui/traits/alias/issue-83613.stderr +++ b/src/test/ui/traits/alias/issue-83613.stderr @@ -6,18 +6,6 @@ LL | impl 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`. diff --git a/src/test/ui/type-alias-impl-trait/coherence.rs b/src/test/ui/type-alias-impl-trait/coherence.rs index 98ac215ad6cc5..077a31494a972 100644 --- a/src/test/ui/type-alias-impl-trait/coherence.rs +++ b/src/test/ui/type-alias-impl-trait/coherence.rs @@ -12,6 +12,6 @@ fn use_alias(val: T) -> AliasOfForeignType { } impl foreign_crate::ForeignTrait for AliasOfForeignType {} -//~^ 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() {} diff --git a/src/test/ui/type-alias-impl-trait/coherence.stderr b/src/test/ui/type-alias-impl-trait/coherence.stderr index 3ce25d94f6e12..c923eb08ab312 100644 --- a/src/test/ui/type-alias-impl-trait/coherence.stderr +++ b/src/test/ui/type-alias-impl-trait/coherence.stderr @@ -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 foreign_crate::ForeignTrait for AliasOfForeignType {} - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------- + | | | + | | `AliasOfForeignType` 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 = 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`. diff --git a/src/test/ui/type-alias-impl-trait/coherence_generalization.rs b/src/test/ui/type-alias-impl-trait/coherence_generalization.rs new file mode 100644 index 0000000000000..5c9ad9498b6de --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/coherence_generalization.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +trait Trait {} +type Opaque = impl Sized; +fn foo() -> Opaque { + () +} + +impl Trait for (T, V, V, u32) {} +impl Trait for (Opaque, V, i32, V) {} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs new file mode 100644 index 0000000000000..0efbd1c2bd5fd --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs @@ -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 {} + +impl Bar<::Assoc> for T {} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs new file mode 100644 index 0000000000000..3f1a9d12b44f9 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs @@ -0,0 +1,33 @@ +#![feature(type_alias_impl_trait)] + +trait Foo {} +impl Foo for () {} +impl Foo for i32 {} + +type Bar = impl std::fmt::Debug; +fn defining_use() -> Bar { + 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 {} +//~^ 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() {} diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr new file mode 100644 index 0000000000000..aaf75cc3db97c --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr @@ -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 {} + | ^^^^^^^^^^^^^^^^^^^^^ 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`. diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs new file mode 100644 index 0000000000000..9f32c5d888b5f --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait.rs @@ -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 {} diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs new file mode 100644 index 0000000000000..8ec20acef4de6 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs @@ -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::(); //~ ERROR: the trait bound `u32: Yay` is not satisfied + is_debug::(); // OK + is_yay::(); // OK + is_debug::(); // OK +} + +fn is_yay() { } +fn is_debug() { } + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr new file mode 100644 index 0000000000000..1c83105a18aff --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr @@ -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::(); + | ^^^ 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() { } + | ^^^ required by this bound in `is_yay` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs new file mode 100644 index 0000000000000..a4b8c2d190db9 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs @@ -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::(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied +} + +fn is_yay() { } + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr new file mode 100644 index 0000000000000..a6440f02c27d8 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr @@ -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::(); + | ^^^ 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() { } + | ^^^ required by this bound in `is_yay` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.rs b/src/test/ui/type-alias-impl-trait/issue-65384.rs index 9a119c4d2e0aa..9a9b2269f802e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-65384.rs +++ b/src/test/ui/type-alias-impl-trait/issue-65384.rs @@ -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 { } diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.stderr b/src/test/ui/type-alias-impl-trait/issue-65384.stderr index 41bcea27e1fa3..f6692ae320733 100644 --- a/src/test/ui/type-alias-impl-trait/issue-65384.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-65384.stderr @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs index fb56cc54d634b..b97e444c6d0e0 100644 --- a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs +++ b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs @@ -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) {} } diff --git a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr b/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr deleted file mode 100644 index 2d4a6854a920b..0000000000000 --- a/src/test/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.stderr +++ /dev/null @@ -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 - diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs index fa25d8f762e6c..2ba4befea2a39 100644 --- a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs +++ b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs @@ -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 { fn f(); } -impl TraitArg for () { //~ ERROR cannot implement trait +impl TraitArg for () { fn f() { println!("ho"); } diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr b/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr deleted file mode 100644 index bb70d07be59bb..0000000000000 --- a/src/test/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.stderr +++ /dev/null @@ -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 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 - diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs index f12d1b6d953cd..48d4b0c96ff0a 100644 --- a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs +++ b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.rs @@ -13,14 +13,14 @@ trait Trait { fn convert(i: In) -> Self::Out; } -impl Trait for Out { //~ ERROR cannot implement trait +impl Trait for Out { type Out = Out; fn convert(_i: In) -> Self::Out { unreachable!(); } } -impl Trait<(), In> for Out { +impl Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait` type Out = In; fn convert(i: In) -> Self::Out { i diff --git a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr index f2d600fb46c54..6a75e1bd2c0fa 100644 --- a/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr @@ -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` + --> $DIR/issue-84660-unsoundness.rs:23:1 | LL | impl Trait 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 Trait<(), In> for Out { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error: aborting due to previous error +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs index ebf3a99bbf9f0..b0ebdd1bfab7d 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs @@ -4,11 +4,11 @@ use std::fmt::Debug; type FooX = impl Debug; +//~^ ERROR unconstrained opaque type trait Foo { } impl Foo for () { } -//~^ cannot implement trait on type alias impl trait fn foo() -> impl Foo { () diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr index 4a3fb16733e04..b1d947a9ccf4e 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -1,14 +1,10 @@ -error: cannot implement trait on type alias impl trait - --> $DIR/nested-tait-inference3.rs:10:10 - | -LL | impl Foo 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 diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 65722f142aa69..d183e28f667c0 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -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 {