diff options
| author | bors <bors@rust-lang.org> | 2022-11-23 06:48:56 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-11-23 06:48:56 +0000 |
| commit | 3f2b2eee8f46f2252d2919d7a57bf3068d7df285 (patch) | |
| tree | 67b05ad47483eb61c39a6f4b5b12862f9991462c /compiler | |
| parent | 008bc1d587b4f9d7197eb159922dd2080eea9284 (diff) | |
| parent | 42afb70f2fc28c52656f49abf4566d17c09123ef (diff) | |
Auto merge of #104758 - Manishearth:rollup-rh1tfum, r=Manishearth
Rollup of 6 pull requests Successful merges: - #103488 (Allow opaque types in trait impl headers and rely on coherence to reject unsound cases) - #104359 (Refactor must_use lint into two parts) - #104612 (Lower return type outside async block creation) - #104621 (Fix --extern library finding errors) - #104647 (enable fuzzy_provenance_casts lint in liballoc and libstd) - #104750 (Bump `fd-lock` in `bootstrap` again) Failed merges: - #104732 (Refactor `ty::ClosureKind` related stuff) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
43 files changed, 470 insertions, 276 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3ab42497d6d..6855344356a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -588,17 +588,12 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, capture_clause: CaptureBy, closure_node_id: NodeId, - ret_ty: Option<AstP<Ty>>, + ret_ty: Option<hir::FnRetTy<'hir>>, span: Span, async_gen_kind: hir::AsyncGeneratorKind, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { - let output = match ret_ty { - Some(ty) => hir::FnRetTy::Return( - self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)), - ), - None => hir::FnRetTy::DefaultReturn(self.lower_span(span)), - }; + let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); // Resume argument type. We let the compiler infer this to simplify the lowering. It is // fully constrained by `future::from_generator`. @@ -1003,8 +998,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // Transform `async |x: u8| -> X { ... }` into // `|x: u8| future_from_generator(|| -> X { ... })`. let body_id = this.lower_fn_body(&outer_decl, |this| { - let async_ret_ty = - if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None }; + let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output { + let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock); + Some(hir::FnRetTy::Return(this.lower_ty(&ty, &itctx))) + } else { + None + }; + let async_body = this.make_async_expr( capture_clause, inner_closure_id, diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 94d51032866..b2702eafd33 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_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index c292ae9b32a..d1e1fd54db9 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -275,7 +275,7 @@ metadata_crate_location_unknown_type = extern location for {$crate_name} is of an unknown type: {$path} metadata_lib_filename_form = - file name should be lib*.rlib or {dll_prefix}*.{dll_suffix} + file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix} metadata_multiple_import_name_type = multiple `import_name_type` arguments in a single `#[link]` attribute diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index a74016e220e..e0b465bab16 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<T: Relate<'tcx>>( &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 71c932d747b..d66b6585fb6 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 55cca0cd2d7..bae43138b4d 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 7534482cce9..f0381353551 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 38499907663..c7bfe99aa9a 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 9d75ccad133..44c3edf06a8 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 5ff3779fa14..2483ab724a4 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 34f54328230..b4a427a5d41 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 c2552561c42..eec938cefbb 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<T>( &mut self, a: ty::Binder<'tcx, T>, @@ -657,6 +675,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { // relatable. Ok(t) } + ty::Opaque(def_id, substs) => { + let s = self.relate(substs, substs)?; + Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) }) + } _ => relate::super_relate_tys(self, t, t), }?; @@ -799,6 +821,11 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { self.infcx.tcx } + fn intercrate(&self) -> bool { + assert!(!self.infcx.intercrate); + false + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } @@ -811,6 +838,10 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { true } + fn mark_ambiguous(&mut self) { + bug!() + } + fn relate_with_variance<T: Relate<'tcx>>( &mut self, _variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 59728148a84..8682f4d3b7a 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 613a05e415f..0dee3be7054 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<T: relate::Relate<'tcx>>( &mut self, _variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 6ffefcb7a28..7f27b35a54e 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<T: Relate<'tcx>>( &mut self, variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index d6e56fcb7fd..97ed4729bd0 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<T: Relate<'tcx>>( &mut self, variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b9ed6b28c22..2798477d181 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<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, + + /// During coherence we have to assume that other crates may add + /// additional impls which we currently don't know about. + /// + /// To deal with this evaluation should be conservative + /// and consider the possibility of impls from outside this crate. + /// This comes up primarily when resolving ambiguity. Imagine + /// there is some trait reference `$0: Bar` where `$0` is an + /// inference variable. If `intercrate` is true, then we can never + /// say for sure that this reference is not implemented, even if + /// there are *no impls at all for `Bar`*, because `$0` could be + /// bound to some type that in a downstream crate that implements + /// `Bar`. + /// + /// Outside of coherence we set this to false because we are only + /// interested in types that the user could actually have written. + /// In other words, we consider `$0: Bar` to be unimplemented if + /// there is no type that the user could *actually name* that + /// would satisfy it. This avoids crippling inference, basically. + pub intercrate: bool, } /// See the `error_reporting` module for more details. @@ -552,6 +572,8 @@ pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, defining_use_anchor: DefiningAnchor, considering_regions: bool, + /// Whether we are in coherence mode. + intercrate: bool, normalize_fn_sig_for_diagnostic: Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, } @@ -567,6 +589,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { defining_use_anchor: DefiningAnchor::Error, considering_regions: true, normalize_fn_sig_for_diagnostic: None, + intercrate: false, } } } @@ -583,6 +606,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> { self } + pub fn intercrate(mut self) -> Self { + self.intercrate = true; + self + } + pub fn ignoring_regions(mut self) -> Self { self.considering_regions = false; self @@ -622,6 +650,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { defining_use_anchor, considering_regions, ref normalize_fn_sig_for_diagnostic, + intercrate, } = *self; InferCtxt { tcx, @@ -641,6 +670,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic .as_ref() .map(|f| f.clone()), + intercrate, } } } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 167a82d4499..4f8460955c3 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<PredicateObligation<'tcx>>, - ) -> Result<(), TypeError<'tcx>>; + fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>); /// Creates a new universe index. Used when instantiating placeholders. fn create_next_universe(&mut self) -> ty::UniverseIndex; @@ -419,7 +415,7 @@ where .infcx .handle_opaque_type(a, b, true, &cause, self.delegate.param_env())? .obligations; - self.delegate.register_opaque_type_obligations(obligations)?; + self.delegate.register_obligations(obligations); trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); Ok(a) } @@ -531,6 +527,10 @@ where self.infcx.tcx } + fn intercrate(&self) -> bool { + self.infcx.intercrate + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.delegate.param_env() } @@ -543,6 +543,17 @@ where true } + fn mark_ambiguous(&mut self) { + let cause = ObligationCause::dummy_with_span(self.delegate.span()); + let param_env = self.delegate.param_env(); + self.delegate.register_obligations(vec![Obligation::new( + self.tcx(), + cause, + param_env, + ty::Binder::dummy(ty::PredicateKind::Ambiguous), + )]); + } + #[instrument(skip(self, info), level = "trace", ret)] fn relate_with_variance<T: Relate<'tcx>>( &mut self, @@ -800,8 +811,12 @@ impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D> where D: TypeRelatingDelegate<'tcx>, { - fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) { - self.delegate.const_equate(a, b); + fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) { + // We don't have to worry about the equality of consts during borrow checking + // as consts always have a static lifetime. + // FIXME(oli-obk): is this really true? We can at least have HKL and with + // inline consts we may have further lifetimes that may be unsound to treat as + // 'static. } } @@ -898,6 +913,11 @@ where self.infcx.tcx } + fn intercrate(&self) -> bool { + assert!(!self.infcx.intercrate); + false + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.delegate.param_env() } @@ -910,6 +930,10 @@ where true } + fn mark_ambiguous(&mut self) { + bug!() + } + fn relate_with_variance<T: Relate<'tcx>>( &mut self, variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 2d19d1823fd..8f780579451 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 a5c21f0fb9b..5d204dd70ed 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<T: Relate<'tcx>>( &mut self, _: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index bd3c5780b89..2c6987cc3f4 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<F, R>(&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 e12c069dcc1..b2a31ac7e6f 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 8c779579a4f..ada3c3b67fb 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_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 100a8788763..0471890230a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::{self, DefIdTree, Ty}; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; +use std::iter; declare_lint! { /// The `unused_must_use` lint detects unused result of a type flagged as @@ -113,30 +114,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } let ty = cx.typeck_results().expr_ty(&expr); - let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, expr.span, "", "", 1); - let mut fn_warned = false; - let mut op_warned = false; - let maybe_def_id = match expr.kind { - hir::ExprKind::Call(ref callee, _) => { - match callee.kind { - hir::ExprKind::Path(ref qpath) => { - match cx.qpath_res(qpath, callee.hir_id) { - Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id), - // `Res::Local` if it was a closure, for which we - // do not currently support must-use linting - _ => None, - } - } - _ => None, - } + let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span); + let type_lint_emitted_or_suppressed = match must_use_result { + Some(path) => { + emit_must_use_untranslated(cx, &path, "", "", 1); + true } - hir::ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id), - _ => None, + None => false, }; - if let Some(def_id) = maybe_def_id { - fn_warned = check_must_use_def(cx, def_id, expr.span, "return value of ", ""); - } else if type_permits_lack_of_use { + + let fn_warned = check_fn_must_use(cx, expr); + + if !fn_warned && type_lint_emitted_or_suppressed { // We don't warn about unused unit or uninhabited types. // (See https://github.com/rust-lang/rust/issues/43806 for details.) return; @@ -170,6 +160,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { _ => None, }; + let mut op_warned = false; + if let Some(must_use_op) = must_use_op { cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint_unused_op, |lint| { lint.set_arg("op", must_use_op) @@ -184,22 +176,64 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { op_warned = true; } - if !(type_permits_lack_of_use || fn_warned || op_warned) { + if !(type_lint_emitted_or_suppressed || fn_warned || op_warned) { cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint_unused_result, |lint| { lint.set_arg("ty", ty) }); } - // Returns whether an error has been emitted (and thus another does not need to be later). - fn check_must_use_ty<'tcx>( + fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + let maybe_def_id = match expr.kind { + hir::ExprKind::Call(ref callee, _) => { + match callee.kind { + hir::ExprKind::Path(ref qpath) => { + match cx.qpath_res(qpath, callee.hir_id) { + Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id), + // `Res::Local` if it was a closure, for which we + // do not currently support must-use linting + _ => None, + } + } + _ => None, + } + } + hir::ExprKind::MethodCall(..) => { + cx.typeck_results().type_dependent_def_id(expr.hir_id) + } + _ => None, + }; + if let Some(def_id) = maybe_def_id { + check_must_use_def(cx, def_id, expr.span, "return value of ", "") + } else { + false + } + } + + /// A path through a type to a must_use source. Contains useful info for the lint. + #[derive(Debug)] + enum MustUsePath { + /// Suppress must_use checking. + Suppressed, + /// The root of the normal must_use lint with an optional message. + Def(Span, DefId, Option<Symbol>), + Boxed(Box<Self>), + Opaque(Box<Self>), + TraitObject(Box<Self>), + TupleElement(Vec<(usize, Self)>), + Array(Box<Self>, u64), + /// The root of the unused_closures lint. + Closure(Span), + /// The root of the unused_generators lint. + Generator(Span), + } + + #[instrument(skip(cx, expr), level = "debug", ret)] + fn is_ty_must_use<'tcx>( cx: &LateContext<'tcx>, ty: Ty<'tcx>, expr: &hir::Expr<'_>, span: Span, - descr_pre: &str, - descr_post: &str, - plural_len: usize, - ) -> bool { + ) -> Option<MustUsePath> { if ty.is_unit() || !ty.is_inhabited_from( cx.tcx, @@ -207,87 +241,164 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { cx.param_env, ) { - return true; + return Some(MustUsePath::Suppressed); } - let plural_suffix = pluralize!(plural_len); - match *ty.kind() { ty::Adt(..) if ty.is_box() => { let boxed_ty = ty.boxed_ty(); - let descr_pre = &format!("{}boxed ", descr_pre); - check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural_len) + is_ty_must_use(cx, boxed_ty, expr, span) + .map(|inner| MustUsePath::Boxed(Box::new(inner))) } - ty::Adt(def, _) => check_must_use_def(cx, def.did(), span, descr_pre, descr_post), + ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Opaque(def, _) => { - let mut has_emitted = false; - for obligation in elaborate_predicates_with_span( + elaborate_predicates_with_span( cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned(), - ) { + ) + .filter_map(|obligation| { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Trait(ref poly_trait_predicate) = obligation.predicate.kind().skip_binder() { let def_id = poly_trait_predicate.trait_ref.def_id; - let descr_pre = - &format!("{}implementer{} of ", descr_pre, plural_suffix,); - if check_must_use_def(cx, def_id, span, descr_pre, descr_post) { - has_emitted = true; - break; - } + + is_def_must_use(cx, def_id, span) + } else { + None } - } - has_emitted + }) + .map(|inner| MustUsePath::Opaque(Box::new(inner))) + .next() } - ty::Dynamic(binder, _, _) => { - let mut has_emitted = false; - for predicate in binder.iter() { + ty::Dynamic(binders, _, _) => binders + .iter() + .filter_map(|predicate| { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { let def_id = trait_ref.def_id; - let descr_post = - &format!(" trait object{}{}", plural_suffix, descr_post,); - if check_must_use_def(cx, def_id, span, descr_pre, descr_post) { - has_emitted = true; - break; - } + is_def_must_use(cx, def_id, span) + } else { + None } - } - has_emitted - } - ty::Tuple(ref tys) => { - let mut has_emitted = false; - let comps = if let hir::ExprKind::Tup(comps) = expr.kind { - debug_assert_eq!(comps.len(), tys.len()); - comps + .map(|inner| MustUsePath::TraitObject(Box::new(inner))) + }) + .next(), + ty::Tuple(tys) => { + let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind { + debug_assert_eq!(elem_exprs.len(), tys.len()); + elem_exprs } else { &[] }; - for (i, ty) in tys.iter().enumerate() { - let descr_post = &format!(" in tuple element {}", i); - let e = comps.get(i).unwrap_or(expr); - let span = e.span; - if check_must_use_ty(cx, ty, e, span, descr_pre, descr_post, plural_len) { - has_emitted = true; - } + + // Default to `expr`. + let elem_exprs = elem_exprs.iter().chain(iter::repeat(expr)); + + let nested_must_use = tys + .iter() + .zip(elem_exprs) + .enumerate() + .filter_map(|(i, (ty, expr))| { + is_ty_must_use(cx, ty, expr, expr.span).map(|path| (i, path)) + }) + .collect::<Vec<_>>(); + + if !nested_must_use.is_empty() { + Some(MustUsePath::TupleElement(nested_must_use)) + } else { + None } - has_emitted } ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) { // If the array is empty we don't lint, to avoid false positives - Some(0) | None => false, + Some(0) | None => None, // If the array is definitely non-empty, we can do `#[must_use]` checking. - Some(n) => { - let descr_pre = &format!("{}array{} of ", descr_pre, plural_suffix,); - check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, n as usize + 1) - } + Some(len) => is_ty_must_use(cx, ty, expr, span) + .map(|inner| MustUsePath::Array(Box::new(inner), len)), }, - ty::Closure(..) => { + ty::Closure(..) => Some(MustUsePath::Closure(span)), + ty::Generator(..) => Some(MustUsePath::Generator(span)), + _ => None, + } + } + + fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> { + if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) { + // check for #[must_use = "..."] + let reason = attr.value_str(); + Some(MustUsePath::Def(span, def_id, reason)) + } else { + None + } + } + + // Returns whether further errors should be suppressed because either a lint has been emitted or the type should be ignored. + fn check_must_use_def( + cx: &LateContext<'_>, + def_id: DefId, + span: Span, + descr_pre_path: &str, + descr_post_path: &str, + ) -> bool { + is_def_must_use(cx, def_id, span) + .map(|must_use_path| { + emit_must_use_untranslated( + cx, + &must_use_path, + descr_pre_path, + descr_post_path, + 1, + ) + }) + .is_some() + } + + #[instrument(skip(cx), level = "debug")] + fn emit_must_use_untranslated( + cx: &LateContext<'_>, + path: &MustUsePath, + descr_pre: &str, + descr_post: &str, + plural_len: usize, + ) { + let plural_suffix = pluralize!(plural_len); + + match path { + MustUsePath::Suppressed => {} + MustUsePath::Boxed(path) => { + let descr_pre = &format!("{}boxed ", descr_pre); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + } + MustUsePath::Opaque(path) => { + let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + } + MustUsePath::TraitObject(path) => { + let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + } + MustUsePath::TupleElement(elems) => { + for (index, path) in elems { + let descr_post = &format!(" in tuple element {}", index); + emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len); + } + } + MustUsePath::Array(path, len) => { + let descr_pre = &format!("{}array{} of ", descr_pre, plural_suffix); + emit_must_use_untranslated( + cx, + path, + descr_pre, + descr_post, + plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)), + ); + } + MustUsePath::Closure(span) => { cx.struct_span_lint( UNUSED_MUST_USE, - span, + *span, fluent::lint_unused_closure, |lint| { // FIXME(davidtwco): this isn't properly translatable because of the @@ -298,12 +409,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { .note(fluent::note) }, ); - true } - ty::Generator(..) => { + MustUsePath::Generator(span) => { cx.struct_span_lint( UNUSED_MUST_USE, - span, + *span, fluent::lint_unused_generator, |lint| { // FIXME(davidtwco): this isn't properly translatable because of the @@ -314,40 +424,20 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { .note(fluent::note) }, ); - true } - _ => false, - } - } - - // Returns whether an error has been emitted (and thus another does not need to be later). - // FIXME: Args desc_{pre,post}_path could be made lazy by taking Fn() -> &str, but this - // would make calling it a big awkward. Could also take String (so args are moved), but - // this would still require a copy into the format string, which would only be executed - // when needed. - fn check_must_use_def( - cx: &LateContext<'_>, - def_id: DefId, - span: Span, - descr_pre_path: &str, - descr_post_path: &str, - ) -> bool { - if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) { - cx.struct_span_lint(UNUSED_MUST_USE, span, fluent::lint_unused_def, |lint| { - // FIXME(davidtwco): this isn't properly translatable because of the pre/post - // strings - lint.set_arg("pre", descr_pre_path); - lint.set_arg("post", descr_post_path); - lint.set_arg("def", cx.tcx.def_path_str(def_id)); - // check for #[must_use = "..."] - if let Some(note) = attr.value_str() { - lint.note(note.as_str()); - } - lint - }); - true - } else { - false + MustUsePath::Def(span, def_id, reason) => { + cx.struct_span_lint(UNUSED_MUST_USE, *span, fluent::lint_unused_def, |lint| { + // FIXME(davidtwco): this isn't properly translatable because of the pre/post + // strings + lint.set_arg("pre", descr_pre); + lint.set_arg("post", descr_post); + lint.set_arg("def", cx.tcx.def_path_str(*def_id)); + if let Some(note) = reason { + lint.note(note.as_str()); + } + lint + }); + } } } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index e5b91d566e5..6f7e6e09ca5 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -692,6 +692,7 @@ pub struct CrateLocationUnknownType<'a> { #[primary_span] pub span: Span, pub path: &'a Path, + pub crate_name: Symbol, } #[derive(Diagnostic)] diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 35f9ef92a1c..15546092e41 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -707,6 +707,12 @@ impl<'a> CrateLocator<'a> { loc.original().clone(), )); } + if !loc.original().is_file() { + return Err(CrateError::ExternLocationNotFile( + self.crate_name, + loc.original().clone(), + )); + } let Some(file) = loc.original().file_name().and_then(|s| s.to_str()) else { return Err(CrateError::ExternLocationNotFile( self.crate_name, @@ -1020,11 +1026,10 @@ impl CrateError { None => String::new(), Some(r) => format!(" which `{}` depends on", r.name), }; - // FIXME: There are no tests for CrateLocationUnknownType or LibFilenameForm if !locator.crate_rejections.via_filename.is_empty() { let mismatches = locator.crate_rejections.via_filename.iter(); for CrateMismatch { path, .. } in mismatches { - sess.emit_err(CrateLocationUnknownType { span, path: &path }); + sess.emit_err(CrateLocationUnknownType { span, path: &path, crate_name }); sess.emit_err(LibFilenameForm { span, dll_prefix: &locator.dll_prefix, diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index e6aab30a150..cd147d7e558 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<T: Relate<'tcx>>( &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 3be0bc4defc..1ee4985cf8d 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<D: Copy + Debug + Eq> SimplifiedTypeGen<D> { | ForeignSimplifiedType(d) | TraitSimplifiedType(d) | ClosureSimplifiedType(d) - | GeneratorSimplifiedType(d) - | OpaqueSimplifiedType(d) => Some(d), + | GeneratorSimplifiedType(d) => Some(d), _ => None, } } @@ -182,7 +179,6 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> { 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 7201737be65..ee4b8f91c54 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 3f26d337d45..0458c4abd3d 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 9c7721bf49a..bddcdd0b693 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2704,6 +2704,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 0adc700586d..3d47b71b7ce 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<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))), diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 6be8fdd7cd7..64b4fd11762 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 a057e45ad6a..78af187cd8f 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 1ef77e06b48..741bf206d03 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 946e6e77a3d..ef3d300020a 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 d84f768cce4..d238e7556ae 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 90f48658113..7c4c58ba361 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 e54e290fb4b..2803a2d38c8 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<IntercrateAmbiguityCause> { - 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<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 @@ 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 53783e1bc4b..5e506a23f38 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 06a42a95d60..ee013515e86 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<chalk_ir::Goal<RustInterner<' | 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 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> 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<chalk_ir::QuantifiedWhereClause<RustInterner<' | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("unexpected predicate {}", &self) } @@ -754,6 +757,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<Ru | ty::PredicateKind::Coerce(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => { 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 82f6111f6f9..2d1a3869926 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 f1835d317e8..5200908527a 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, } } |
