diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3ab42497d6d4f..6855344356a1f 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>, + ret_ty: Option>, 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 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_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index c292ae9b32abb..d1e1fd54db9bf 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 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/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 6cf9e23b40b0e..50714d632c697 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); let kind = object_type .principal_def_id() - .and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did)); + .and_then(|did| self.tcx.fn_trait_kind_from_def_id(did)); (sig, kind) } ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates( @@ -235,7 +235,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }; if let Some(closure_kind) = - trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_lang_item(def_id)) + trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_def_id(def_id)) { expected_kind = Some( expected_kind @@ -263,7 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_def_id = projection.trait_def_id(tcx); - let is_fn = tcx.fn_trait_kind_from_lang_item(trait_def_id).is_some(); + let is_fn = tcx.is_fn_trait(trait_def_id); let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span); let is_gen = gen_trait == trait_def_id; if !is_fn && !is_gen { 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/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index a31ab9c8b23b8..f5f8ebe90b11e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2097,7 +2097,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id) && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id) // Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce" - && let Some(call_kind) = ty::ClosureKind::from_def_id(self.tcx, maybe_trait_def_id) + && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id) && let Some(callee_ty) = callee_ty { let callee_ty = callee_ty.peel_refs(); @@ -2123,7 +2123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if let ty::PredicateKind::Trait(pred) = predicate.kind().skip_binder() && pred.self_ty().peel_refs() == callee_ty - && ty::ClosureKind::from_def_id(self.tcx, pred.def_id()).is_some() + && self.tcx.is_fn_trait(pred.def_id()) { err.span_note(span, "callable defined here"); return; 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/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index a585168294a29..1f554c81eff8e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -399,10 +399,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); if self_ty.value.is_closure() - && self - .tcx() - .fn_trait_kind_from_lang_item(expected_trait_ref.value.def_id) - .is_some() + && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) { let closure_sig = self_ty.map(|closure| { if let ty::Closure(_, substs) = closure.kind() { 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_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 100a8788763c2..0471890230aa6 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), + Boxed(Box), + Opaque(Box), + TraitObject(Box), + TupleElement(Vec<(usize, Self)>), + Array(Box, 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 { 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::>(); + + 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 { + 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 e5b91d566e524..6f7e6e09ca5ed 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 35f9ef92a1c42..15546092e41a2 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/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index dd4332d0db6d2..343ea1f00f58b 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -27,7 +27,10 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn fn_trait_kind_from_lang_item(self, id: DefId) -> Option { + /// Given a [`DefId`] of a [`Fn`], [`FnMut`] or [`FnOnce`] traits, + /// returns a corresponding [`ty::ClosureKind`]. + /// For any other [`DefId`] return `None`. + pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option { let items = self.lang_items(); match Some(id) { x if x == items.fn_trait() => Some(ty::ClosureKind::Fn), @@ -36,6 +39,11 @@ impl<'tcx> TyCtxt<'tcx> { _ => None, } } + + /// Returns `true` if `id` is a `DefId` of [`Fn`], [`FnMut`] or [`FnOnce`] traits. + pub fn is_fn_trait(self, id: DefId) -> bool { + self.fn_trait_kind_from_def_id(id).is_some() + } } /// Returns `true` if the specified `lang_item` must be present for this 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/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 0d6c26a582246..2204677b1338a 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -96,15 +96,18 @@ impl<'tcx> ClosureKind { /// Returns `true` if a type that impls this closure kind /// must also implement `other`. pub fn extends(self, other: ty::ClosureKind) -> bool { - matches!( - (self, other), - (ClosureKind::Fn, ClosureKind::Fn) - | (ClosureKind::Fn, ClosureKind::FnMut) - | (ClosureKind::Fn, ClosureKind::FnOnce) - | (ClosureKind::FnMut, ClosureKind::FnMut) - | (ClosureKind::FnMut, ClosureKind::FnOnce) - | (ClosureKind::FnOnce, ClosureKind::FnOnce) - ) + self <= other + } + + /// Converts `self` to a [`DefId`] of the corresponding trait. + /// + /// Note: the inverse of this function is [`TyCtxt::fn_trait_kind_from_def_id`]. + pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId { + match self { + ClosureKind::Fn => tcx.lang_items().fn_once_trait().unwrap(), + ClosureKind::FnMut => tcx.lang_items().fn_mut_trait().unwrap(), + ClosureKind::FnOnce => tcx.lang_items().fn_trait().unwrap(), + } } /// Returns the representative scalar type for this closure kind. @@ -116,26 +119,6 @@ impl<'tcx> ClosureKind { ClosureKind::FnOnce => tcx.types.i32, } } - - pub fn from_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if Some(def_id) == tcx.lang_items().fn_once_trait() { - Some(ClosureKind::FnOnce) - } else if Some(def_id) == tcx.lang_items().fn_mut_trait() { - Some(ClosureKind::FnMut) - } else if Some(def_id) == tcx.lang_items().fn_trait() { - Some(ClosureKind::Fn) - } else { - None - } - } - - pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId { - match self { - ClosureKind::Fn => tcx.lang_items().fn_once_trait().unwrap(), - ClosureKind::FnMut => tcx.lang_items().fn_mut_trait().unwrap(), - ClosureKind::FnOnce => tcx.lang_items().fn_trait().unwrap(), - } - } } /// A composite describing a `Place` that is captured by a closure. 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..4ee1b10ea95ac 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1073,7 +1073,7 @@ pub trait PrettyPrinter<'tcx>: let mut resugared = false; // Special-case `Fn(...) -> ...` and re-sugar it. - let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id); + let fn_trait_kind = cx.tcx().fn_trait_kind_from_def_id(principal.def_id); if !cx.should_print_verbose() && fn_trait_kind.is_some() { if let ty::Tuple(tys) = principal.substs.type_at(0).kind() { let mut projections = predicates.projection_bounds(); @@ -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_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index db18558e947a3..6d303c3b38840 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2130,8 +2130,7 @@ impl<'tcx> Ty<'tcx> { /// parameter. This is kind of a phantom type, except that the /// most convenient thing for us to are the integral types. This /// function converts such a special type into the closure - /// kind. To go the other way, use - /// `tcx.closure_kind_ty(closure_kind)`. + /// kind. To go the other way, use `closure_kind.to_ty(tcx)`. /// /// Note that during type checking, we use an inference variable /// to represent the closure kind, because it has not yet been diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 68703eb0a232e..a115bb2831a4b 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -37,7 +37,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' } ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); - let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) { + let adjustment = match tcx.fn_trait_kind_from_def_id(trait_) { Some(ty::ClosureKind::FnOnce) => Adjustment::Identity, Some(ty::ClosureKind::FnMut | ty::ClosureKind::Fn) => Adjustment::Deref, None => bug!("fn pointer {:?} is not an fn", ty), 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..4250fb79069ed 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -358,7 +358,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { fulfill_cx.register_predicate_obligation(self, obligation); if fulfill_cx.select_all_or_error(self).is_empty() { return Ok(( - ty::ClosureKind::from_def_id(self.tcx, trait_def_id) + self.tcx + .fn_trait_kind_from_def_id(trait_def_id) .expect("expected to map DefId to ClosureKind"), ty.rebind(self.resolve_vars_if_possible(var)), )); @@ -687,7 +688,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ItemObligation(def_id) - if ty::ClosureKind::from_def_id(tcx, *def_id).is_some() => + if tcx.is_fn_trait(*def_id) => { err.code(rustc_errors::error_code!(E0059)); err.set_primary_message(format!( @@ -847,8 +848,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } - let is_fn_trait = - ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some(); + let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id()); let is_target_feature_fn = if let ty::FnDef(def_id, _) = *trait_ref.skip_binder().self_ty().kind() { @@ -878,7 +878,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Note if the `FnMut` or `FnOnce` is less general than the trait we're trying // to implement. let selected_kind = - ty::ClosureKind::from_def_id(self.tcx, trait_ref.def_id()) + self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) .expect("expected to map DefId to ClosureKind"); if !implemented_kind.extends(selected_kind) { err.note( @@ -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" @@ -2152,7 +2154,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if generics.params.iter().any(|p| p.name != kw::SelfUpper) && !snippet.ends_with('>') && !generics.has_impl_trait() - && !self.tcx.fn_trait_kind_from_lang_item(def_id).is_some() + && !self.tcx.is_fn_trait(def_id) { // FIXME: To avoid spurious suggestions in functions where type arguments // where already supplied, we check the snippet to make sure it doesn't diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 8086cac0d551a..eeb9ee7fd131f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1684,9 +1684,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> Ty<'tcx> { let inputs = trait_ref.skip_binder().substs.type_at(1); let sig = match inputs.kind() { - ty::Tuple(inputs) - if infcx.tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some() => - { + ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => { infcx.tcx.mk_fn_sig( inputs.iter(), infcx.next_ty_var(TypeVariableOrigin { @@ -1757,7 +1755,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx) && let Some(pred) = predicates.predicates.get(*idx) && let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() - && ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id()).is_some() + && self.tcx.is_fn_trait(trait_pred.def_id()) { let expected_self = self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty())); @@ -1771,8 +1769,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .enumerate() .find(|(other_idx, (pred, _))| match pred.kind().skip_binder() { ty::PredicateKind::Trait(trait_pred) - if ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id()) - .is_some() + if self.tcx.is_fn_trait(trait_pred.def_id()) && other_idx != idx // Make sure that the self type matches // (i.e. constraining this closure) 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/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3b107d9570f14..1ce321756c19c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -435,7 +435,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - let Some(kind) = self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()) else { + let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else { return; }; @@ -473,7 +473,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) { // We provide impl of all fn traits for fn pointers. - if self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()).is_none() { + if !self.tcx().is_fn_trait(obligation.predicate.def_id()) { return; } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2ec5d925b6900..60d0618d4f3e7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -700,7 +700,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result>, SelectionError<'tcx>> { let kind = self .tcx() - .fn_trait_kind_from_lang_item(obligation.predicate.def_id()) + .fn_trait_kind_from_def_id(obligation.predicate.def_id()) .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation)); // Okay to skip binder because the substs on closure types never 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/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 6436713b38811..c25ba7535e221 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -203,7 +203,7 @@ fn resolve_associated_item<'tcx>( substs: generator_data.substs, }), traits::ImplSource::Closure(closure_data) => { - let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap(); + let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap(); Instance::resolve_closure( tcx, closure_data.closure_def_id, diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs index d418965cd2f6b..b25d63d835b54 100644 --- a/library/alloc/benches/lib.rs +++ b/library/alloc/benches/lib.rs @@ -5,7 +5,9 @@ #![feature(iter_next_chunk)] #![feature(repr_simd)] #![feature(slice_partition_dedup)] +#![feature(strict_provenance)] #![feature(test)] +#![deny(fuzzy_provenance_casts)] extern crate test; diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 5e13547abcb70..96960d43f5820 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -82,6 +82,7 @@ // // Lints: #![deny(unsafe_op_in_unsafe_fn)] +#![deny(fuzzy_provenance_casts)] #![warn(deprecated_in_future)] #![warn(missing_debug_implementations)] #![warn(missing_docs)] diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs index 5ee6db43fda24..04da95bbb83ed 100644 --- a/library/alloc/tests/fmt.rs +++ b/library/alloc/tests/fmt.rs @@ -2,6 +2,7 @@ use std::cell::RefCell; use std::fmt::{self, Write}; +use std::ptr; #[test] fn test_format() { @@ -76,14 +77,14 @@ fn test_format_macro_interface() { t!(format!("{}", "foo"), "foo"); t!(format!("{}", "foo".to_string()), "foo"); if cfg!(target_pointer_width = "32") { - t!(format!("{:#p}", 0x1234 as *const isize), "0x00001234"); - t!(format!("{:#p}", 0x1234 as *mut isize), "0x00001234"); + t!(format!("{:#p}", ptr::invalid::(0x1234)), "0x00001234"); + t!(format!("{:#p}", ptr::invalid_mut::(0x1234)), "0x00001234"); } else { - t!(format!("{:#p}", 0x1234 as *const isize), "0x0000000000001234"); - t!(format!("{:#p}", 0x1234 as *mut isize), "0x0000000000001234"); + t!(format!("{:#p}", ptr::invalid::(0x1234)), "0x0000000000001234"); + t!(format!("{:#p}", ptr::invalid_mut::(0x1234)), "0x0000000000001234"); } - t!(format!("{:p}", 0x1234 as *const isize), "0x1234"); - t!(format!("{:p}", 0x1234 as *mut isize), "0x1234"); + t!(format!("{:p}", ptr::invalid::(0x1234)), "0x1234"); + t!(format!("{:p}", ptr::invalid_mut::(0x1234)), "0x1234"); t!(format!("{A:x}"), "aloha"); t!(format!("{B:X}"), "adios"); t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃"); diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index ffc5ca7a5c6cc..d066ec03ee57e 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -47,6 +47,7 @@ #![feature(strict_provenance)] #![feature(once_cell)] #![feature(drain_keep_rest)] +#![deny(fuzzy_provenance_casts)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 63ee6c521d793..65d4c3c891ea6 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -220,6 +220,7 @@ #![allow(explicit_outlives_requirements)] #![allow(unused_lifetimes)] #![deny(rustc::existing_doc_keyword)] +#![deny(fuzzy_provenance_casts)] // Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind` #![deny(ffi_unwind_calls)] // std may use features in a platform-specific way @@ -598,7 +599,7 @@ mod panicking; mod personality; #[path = "../../backtrace/src/lib.rs"] -#[allow(dead_code, unused_attributes)] +#[allow(dead_code, unused_attributes, fuzzy_provenance_casts)] mod backtrace_rs; // Re-export macros defined in libcore. diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index 72cb3406dcada..5c1634084a055 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -90,6 +90,7 @@ impl OwnedSocket { } // FIXME(strict_provenance_magic): we defined RawSocket to be a u64 ;-; + #[allow(fuzzy_provenance_casts)] #[cfg(not(target_vendor = "uwp"))] pub(crate) fn set_no_inherit(&self) -> io::Result<()> { cvt(unsafe { diff --git a/library/std/src/personality/dwarf/eh.rs b/library/std/src/personality/dwarf/eh.rs index 27b50c13b77ca..a783e187004fc 100644 --- a/library/std/src/personality/dwarf/eh.rs +++ b/library/std/src/personality/dwarf/eh.rs @@ -13,6 +13,7 @@ use super::DwarfReader; use core::mem; +use core::ptr; pub const DW_EH_PE_omit: u8 = 0xFF; pub const DW_EH_PE_absptr: u8 = 0x00; @@ -151,7 +152,7 @@ unsafe fn read_encoded_pointer( // DW_EH_PE_aligned implies it's an absolute pointer value if encoding == DW_EH_PE_aligned { - reader.ptr = round_up(reader.ptr as usize, mem::size_of::())? as *const u8; + reader.ptr = reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::())?); return Ok(reader.read::()); } @@ -171,7 +172,7 @@ unsafe fn read_encoded_pointer( result += match encoding & 0x70 { DW_EH_PE_absptr => 0, // relative to address of the encoded value, despite the name - DW_EH_PE_pcrel => reader.ptr as usize, + DW_EH_PE_pcrel => reader.ptr.expose_addr(), DW_EH_PE_funcrel => { if context.func_start == 0 { return Err(()); @@ -184,7 +185,7 @@ unsafe fn read_encoded_pointer( }; if encoding & DW_EH_PE_indirect != 0 { - result = *(result as *const usize); + result = *ptr::from_exposed_addr::(result); } Ok(result) diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index b1d32929ecfde..01e4ffe3dfc8a 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -3,6 +3,7 @@ //! This module contains the facade (aka platform-specific) implementations of //! OS level functionality for Fortanix SGX. #![deny(unsafe_op_in_unsafe_fn)] +#![allow(fuzzy_provenance_casts)] // FIXME: this entire module systematically confuses pointers and integers use crate::io::ErrorKind; use crate::sync::atomic::{AtomicBool, Ordering}; diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 0cd778a0cbb1d..fe8a028dfd3ad 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -225,13 +225,13 @@ dependencies = [ [[package]] name = "fd-lock" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c93a581058d957dc4176875aad04f82f81613e6611d64aa1a9c755bdfb16711" +checksum = "bb21c69b9fea5e15dbc1049e4b77145dd0ba1c84019c488102de0dc4ea4b0a27" dependencies = [ "cfg-if", "rustix", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -319,9 +319,13 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "0.7.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c3f4eff5495aee4c0399d7b6a0dc2b6e81be84242ffbfcf253ebacccc1d0cb" +checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87" +dependencies = [ + "libc", + "windows-sys", +] [[package]] name = "itoa" @@ -337,15 +341,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "linux-raw-sys" -version = "0.0.46" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" +checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f" [[package]] name = "log" @@ -529,16 +533,16 @@ checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" [[package]] name = "rustix" -version = "0.35.6" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef258c11e17f5c01979a10543a30a4e12faef6aab217a74266e747eefa3aed88" +checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.36.1", + "windows-sys", ] [[package]] @@ -725,19 +729,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - [[package]] name = "windows-sys" version = "0.42.0" @@ -745,12 +736,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc", ] [[package]] @@ -759,48 +750,24 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - [[package]] name = "windows_aarch64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - [[package]] name = "windows_i686_gnu" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - [[package]] name = "windows_i686_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - [[package]] name = "windows_x86_64_gnu" version = "0.42.0" @@ -813,12 +780,6 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - [[package]] name = "windows_x86_64_msvc" version = "0.42.0" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 4c24c214d2c54..8751a71caf1b4 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -36,7 +36,7 @@ test = false [dependencies] cmake = "0.1.38" -fd-lock = "3.0.7" +fd-lock = "3.0.8" filetime = "0.2" getopts = "0.2.19" cc = "1.0.69" 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/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 35e2720fdff89..d540d828d3b10 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -106,7 +106,7 @@ fn external_generic_args<'tcx>( ) -> GenericArgs { let args = substs_to_args(cx, substs, has_self); - if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() { + if cx.tcx.fn_trait_kind_from_def_id(did).is_some() { let inputs = // The trait's first substitution is the one after self, if there is one. match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() { 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/errors/issue-104621-extern-bad-file.rs b/src/test/ui/errors/issue-104621-extern-bad-file.rs new file mode 100644 index 0000000000000..3f13d60523203 --- /dev/null +++ b/src/test/ui/errors/issue-104621-extern-bad-file.rs @@ -0,0 +1,8 @@ +// compile-flags: --extern foo={{src-base}}/errors/issue-104621-extern-bad-file.rs +// only-linux + +extern crate foo; +//~^ ERROR extern location for foo is of an unknown type +//~| ERROR file name should be lib*.rlib or lib*.so +//~| ERROR can't find crate for `foo` [E0463] +fn main() {} diff --git a/src/test/ui/errors/issue-104621-extern-bad-file.stderr b/src/test/ui/errors/issue-104621-extern-bad-file.stderr new file mode 100644 index 0000000000000..b8500ad0e045b --- /dev/null +++ b/src/test/ui/errors/issue-104621-extern-bad-file.stderr @@ -0,0 +1,21 @@ +error: extern location for foo is of an unknown type: $DIR/issue-104621-extern-bad-file.rs + --> $DIR/issue-104621-extern-bad-file.rs:4:1 + | +LL | extern crate foo; + | ^^^^^^^^^^^^^^^^^ + +error: file name should be lib*.rlib or lib*.so + --> $DIR/issue-104621-extern-bad-file.rs:4:1 + | +LL | extern crate foo; + | ^^^^^^^^^^^^^^^^^ + +error[E0463]: can't find crate for `foo` + --> $DIR/issue-104621-extern-bad-file.rs:4:1 + | +LL | extern crate foo; + | ^^^^^^^^^^^^^^^^^ can't find crate + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/errors/issue-104621-extern-not-file.rs b/src/test/ui/errors/issue-104621-extern-not-file.rs new file mode 100644 index 0000000000000..899e45a306b05 --- /dev/null +++ b/src/test/ui/errors/issue-104621-extern-not-file.rs @@ -0,0 +1,4 @@ +// compile-flags: --extern foo=. + +extern crate foo; //~ ERROR extern location for foo is not a file: . +fn main() {} diff --git a/src/test/ui/errors/issue-104621-extern-not-file.stderr b/src/test/ui/errors/issue-104621-extern-not-file.stderr new file mode 100644 index 0000000000000..5aaf9741360ef --- /dev/null +++ b/src/test/ui/errors/issue-104621-extern-not-file.stderr @@ -0,0 +1,8 @@ +error: extern location for foo is not a file: . + --> $DIR/issue-104621-extern-not-file.rs:3:1 + | +LL | extern crate foo; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + 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/lint/unused/must-use-ops.rs b/src/test/ui/lint/unused/must-use-ops.rs index 3e425727e7829..60f877aa8b303 100644 --- a/src/test/ui/lint/unused/must-use-ops.rs +++ b/src/test/ui/lint/unused/must-use-ops.rs @@ -3,12 +3,18 @@ // check-pass #![warn(unused_must_use)] +#![feature(never_type)] + +fn deref_never(x: &!) { + // Don't lint for uninhabited typess + *x; +} fn main() { let val = 1; let val_pointer = &val; -// Comparison Operators + // Comparison Operators val == 1; //~ WARNING unused comparison val < 1; //~ WARNING unused comparison val <= 1; //~ WARNING unused comparison @@ -16,26 +22,30 @@ fn main() { val >= 1; //~ WARNING unused comparison val > 1; //~ WARNING unused comparison -// Arithmetic Operators + // Arithmetic Operators val + 2; //~ WARNING unused arithmetic operation val - 2; //~ WARNING unused arithmetic operation val / 2; //~ WARNING unused arithmetic operation val * 2; //~ WARNING unused arithmetic operation val % 2; //~ WARNING unused arithmetic operation -// Logical Operators + // Logical Operators true && true; //~ WARNING unused logical operation false || true; //~ WARNING unused logical operation -// Bitwise Operators + // Bitwise Operators 5 ^ val; //~ WARNING unused bitwise operation 5 & val; //~ WARNING unused bitwise operation 5 | val; //~ WARNING unused bitwise operation 5 << val; //~ WARNING unused bitwise operation 5 >> val; //~ WARNING unused bitwise operation -// Unary Operators + // Unary Operators !val; //~ WARNING unused unary operation -val; //~ WARNING unused unary operation *val_pointer; //~ WARNING unused unary operation + + if false { + deref_never(&panic!()); + } } diff --git a/src/test/ui/lint/unused/must-use-ops.stderr b/src/test/ui/lint/unused/must-use-ops.stderr index b248dd0fe1547..79a53d39cbf10 100644 --- a/src/test/ui/lint/unused/must-use-ops.stderr +++ b/src/test/ui/lint/unused/must-use-ops.stderr @@ -1,5 +1,5 @@ warning: unused comparison that must be used - --> $DIR/must-use-ops.rs:12:5 + --> $DIR/must-use-ops.rs:18:5 | LL | val == 1; | ^^^^^^^^ the comparison produces a value @@ -15,7 +15,7 @@ LL | let _ = val == 1; | +++++++ warning: unused comparison that must be used - --> $DIR/must-use-ops.rs:13:5 + --> $DIR/must-use-ops.rs:19:5 | LL | val < 1; | ^^^^^^^ the comparison produces a value @@ -26,7 +26,7 @@ LL | let _ = val < 1; | +++++++ warning: unused comparison that must be used - --> $DIR/must-use-ops.rs:14:5 + --> $DIR/must-use-ops.rs:20:5 | LL | val <= 1; | ^^^^^^^^ the comparison produces a value @@ -37,7 +37,7 @@ LL | let _ = val <= 1; | +++++++ warning: unused comparison that must be used - --> $DIR/must-use-ops.rs:15:5 + --> $DIR/must-use-ops.rs:21:5 | LL | val != 1; | ^^^^^^^^ the comparison produces a value @@ -48,7 +48,7 @@ LL | let _ = val != 1; | +++++++ warning: unused comparison that must be used - --> $DIR/must-use-ops.rs:16:5 + --> $DIR/must-use-ops.rs:22:5 | LL | val >= 1; | ^^^^^^^^ the comparison produces a value @@ -59,7 +59,7 @@ LL | let _ = val >= 1; | +++++++ warning: unused comparison that must be used - --> $DIR/must-use-ops.rs:17:5 + --> $DIR/must-use-ops.rs:23:5 | LL | val > 1; | ^^^^^^^ the comparison produces a value @@ -70,7 +70,7 @@ LL | let _ = val > 1; | +++++++ warning: unused arithmetic operation that must be used - --> $DIR/must-use-ops.rs:20:5 + --> $DIR/must-use-ops.rs:26:5 | LL | val + 2; | ^^^^^^^ the arithmetic operation produces a value @@ -81,7 +81,7 @@ LL | let _ = val + 2; | +++++++ warning: unused arithmetic operation that must be used - --> $DIR/must-use-ops.rs:21:5 + --> $DIR/must-use-ops.rs:27:5 | LL | val - 2; | ^^^^^^^ the arithmetic operation produces a value @@ -92,7 +92,7 @@ LL | let _ = val - 2; | +++++++ warning: unused arithmetic operation that must be used - --> $DIR/must-use-ops.rs:22:5 + --> $DIR/must-use-ops.rs:28:5 | LL | val / 2; | ^^^^^^^ the arithmetic operation produces a value @@ -103,7 +103,7 @@ LL | let _ = val / 2; | +++++++ warning: unused arithmetic operation that must be used - --> $DIR/must-use-ops.rs:23:5 + --> $DIR/must-use-ops.rs:29:5 | LL | val * 2; | ^^^^^^^ the arithmetic operation produces a value @@ -114,7 +114,7 @@ LL | let _ = val * 2; | +++++++ warning: unused arithmetic operation that must be used - --> $DIR/must-use-ops.rs:24:5 + --> $DIR/must-use-ops.rs:30:5 | LL | val % 2; | ^^^^^^^ the arithmetic operation produces a value @@ -125,7 +125,7 @@ LL | let _ = val % 2; | +++++++ warning: unused logical operation that must be used - --> $DIR/must-use-ops.rs:27:5 + --> $DIR/must-use-ops.rs:33:5 | LL | true && true; | ^^^^^^^^^^^^ the logical operation produces a value @@ -136,7 +136,7 @@ LL | let _ = true && true; | +++++++ warning: unused logical operation that must be used - --> $DIR/must-use-ops.rs:28:5 + --> $DIR/must-use-ops.rs:34:5 | LL | false || true; | ^^^^^^^^^^^^^ the logical operation produces a value @@ -147,7 +147,7 @@ LL | let _ = false || true; | +++++++ warning: unused bitwise operation that must be used - --> $DIR/must-use-ops.rs:31:5 + --> $DIR/must-use-ops.rs:37:5 | LL | 5 ^ val; | ^^^^^^^ the bitwise operation produces a value @@ -158,7 +158,7 @@ LL | let _ = 5 ^ val; | +++++++ warning: unused bitwise operation that must be used - --> $DIR/must-use-ops.rs:32:5 + --> $DIR/must-use-ops.rs:38:5 | LL | 5 & val; | ^^^^^^^ the bitwise operation produces a value @@ -169,7 +169,7 @@ LL | let _ = 5 & val; | +++++++ warning: unused bitwise operation that must be used - --> $DIR/must-use-ops.rs:33:5 + --> $DIR/must-use-ops.rs:39:5 | LL | 5 | val; | ^^^^^^^ the bitwise operation produces a value @@ -180,7 +180,7 @@ LL | let _ = 5 | val; | +++++++ warning: unused bitwise operation that must be used - --> $DIR/must-use-ops.rs:34:5 + --> $DIR/must-use-ops.rs:40:5 | LL | 5 << val; | ^^^^^^^^ the bitwise operation produces a value @@ -191,7 +191,7 @@ LL | let _ = 5 << val; | +++++++ warning: unused bitwise operation that must be used - --> $DIR/must-use-ops.rs:35:5 + --> $DIR/must-use-ops.rs:41:5 | LL | 5 >> val; | ^^^^^^^^ the bitwise operation produces a value @@ -202,7 +202,7 @@ LL | let _ = 5 >> val; | +++++++ warning: unused unary operation that must be used - --> $DIR/must-use-ops.rs:38:5 + --> $DIR/must-use-ops.rs:44:5 | LL | !val; | ^^^^ the unary operation produces a value @@ -213,7 +213,7 @@ LL | let _ = !val; | +++++++ warning: unused unary operation that must be used - --> $DIR/must-use-ops.rs:39:5 + --> $DIR/must-use-ops.rs:45:5 | LL | -val; | ^^^^ the unary operation produces a value @@ -224,7 +224,7 @@ LL | let _ = -val; | +++++++ warning: unused unary operation that must be used - --> $DIR/must-use-ops.rs:40:5 + --> $DIR/must-use-ops.rs:46:5 | LL | *val_pointer; | ^^^^^^^^^^^^ the unary operation produces a value diff --git a/src/test/ui/lint/unused/must_use-array.rs b/src/test/ui/lint/unused/must_use-array.rs index 97825dd2f6c43..b7bae4b0acf12 100644 --- a/src/test/ui/lint/unused/must_use-array.rs +++ b/src/test/ui/lint/unused/must_use-array.rs @@ -1,6 +1,7 @@ #![deny(unused_must_use)] #[must_use] +#[derive(Clone, Copy)] struct S; struct A; @@ -34,6 +35,10 @@ fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] { [[[S], [S]]] } +fn usize_max() -> [S; usize::MAX] { + [S; usize::MAX] +} + fn main() { empty(); // ok singleton(); //~ ERROR unused array of `S` that must be used @@ -44,4 +49,6 @@ fn main() { //~^ ERROR unused array of boxed `T` trait objects in tuple element 1 that must be used array_of_arrays_of_arrays(); //~^ ERROR unused array of arrays of arrays of `S` that must be used + usize_max(); + //~^ ERROR unused array of `S` that must be used } diff --git a/src/test/ui/lint/unused/must_use-array.stderr b/src/test/ui/lint/unused/must_use-array.stderr index bba2b1ba078c6..61ef2088d30e5 100644 --- a/src/test/ui/lint/unused/must_use-array.stderr +++ b/src/test/ui/lint/unused/must_use-array.stderr @@ -1,5 +1,5 @@ error: unused array of `S` that must be used - --> $DIR/must_use-array.rs:39:5 + --> $DIR/must_use-array.rs:44:5 | LL | singleton(); | ^^^^^^^^^^^ @@ -11,34 +11,40 @@ LL | #![deny(unused_must_use)] | ^^^^^^^^^^^^^^^ error: unused array of `S` that must be used - --> $DIR/must_use-array.rs:40:5 + --> $DIR/must_use-array.rs:45:5 | LL | many(); | ^^^^^^ error: unused array of `S` in tuple element 0 that must be used - --> $DIR/must_use-array.rs:41:6 + --> $DIR/must_use-array.rs:46:6 | LL | ([S], 0, ()); | ^^^ error: unused array of implementers of `T` that must be used - --> $DIR/must_use-array.rs:42:5 + --> $DIR/must_use-array.rs:47:5 | LL | array_of_impl_trait(); | ^^^^^^^^^^^^^^^^^^^^^ error: unused array of boxed `T` trait objects in tuple element 1 that must be used - --> $DIR/must_use-array.rs:43:5 + --> $DIR/must_use-array.rs:48:5 | LL | impl_array(); | ^^^^^^^^^^^^ error: unused array of arrays of arrays of `S` that must be used - --> $DIR/must_use-array.rs:45:5 + --> $DIR/must_use-array.rs:50:5 | LL | array_of_arrays_of_arrays(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: unused array of `S` that must be used + --> $DIR/must_use-array.rs:52:5 + | +LL | usize_max(); + | ^^^^^^^^^^^ + +error: aborting due to 7 previous errors 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 {