diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 0dbee8c1d948e..a50b50d231d78 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -241,10 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { variant_index: VariantIdx, ) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> { match self.layout_of(ty)?.variants { - abi::Variants::Single { index } => { - assert_eq!(index, variant_index); - Ok(None) - } + abi::Variants::Single { .. } => Ok(None), abi::Variants::Multiple { tag_encoding: TagEncoding::Direct, diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index e28cc05cc2a80..ba819853ea06b 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1057,7 +1057,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false, - ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)), + ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)), ty::Pat(ty, ..) => is_very_trivially_sized(*ty), diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 5461e9c6ad3f6..9a26ac04b85a3 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -446,7 +446,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?; // Test bounds. // It is sufficient to check this for the end pointer. Also check for overflow! - if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) { + if offset.checked_add(size, &self.tcx).is_none_or(|end| end > alloc_size) { throw_ub!(PointerOutOfBounds { alloc_id, alloc_size, diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 09e1a59dfa1a7..efa01b5434260 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -300,7 +300,7 @@ where ) -> InterpResult<'tcx, P> { let len = base.len(self)?; // also asserts that we have a type where this makes sense let actual_to = if from_end { - if from.checked_add(to).map_or(true, |to| to > len) { + if from.checked_add(to).is_none_or(|to| to > len) { // This can only be reached in ConstProp and non-rustc-MIR. throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) }); } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 45ea3ec08f8f4..50a4d0612ccd3 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -6,6 +6,7 @@ #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] +#![feature(is_none_or)] #![feature(let_chains)] #![feature(never_type)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 042894beec221..458f1f14cbb73 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1633,6 +1633,13 @@ pub struct ConstBlock { } /// An expression. +/// +/// For more details, see the [rust lang reference]. +/// Note that the reference does not document nightly-only features. +/// There may be also slight differences in the names and representation of AST nodes between +/// the compiler and the reference. +/// +/// [rust lang reference]: https://doc.rust-lang.org/reference/expressions.html #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Expr<'hir> { pub hir_id: HirId, @@ -3147,6 +3154,13 @@ impl ItemId { /// An item /// /// The name might be a dummy name in case of anonymous items +/// +/// For more details, see the [rust lang reference]. +/// Note that the reference does not document nightly-only features. +/// There may be also slight differences in the names and representation of AST nodes between +/// the compiler and the reference. +/// +/// [rust lang reference]: https://doc.rust-lang.org/reference/items.html #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Item<'hir> { pub ident: Ident, diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index a599e8d05fd3c..281af80bff577 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -234,7 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ret_ty = ret_coercion.borrow().expected_ty(); let ret_ty = self.infcx.shallow_resolve(ret_ty); self.can_coerce(arm_ty, ret_ty) - && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty)) + && prior_arm.is_none_or(|(_, ty, _)| self.can_coerce(ty, ret_ty)) // The match arms need to unify for the case of `impl Trait`. && !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..)) } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index e54a07786cd1d..fcd22b746769c 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -913,7 +913,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { if self .tcx .upvars_mentioned(closure_def_id_a.expect_local()) - .map_or(true, |u| u.is_empty()) => + .is_none_or(|u| u.is_empty()) => { // We coerce the closure, which has fn type // `extern "rust-call" fn((arg0,arg1,...)) -> _` diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 3321f029c8d8c..7fd081593854d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1557,7 +1557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we // don't copy that one element, we move it. Only check for Copy if the length is larger. - if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) { + if count.try_eval_target_usize(tcx, self.param_env).is_none_or(|len| len > 1) { let lang_item = self.tcx.require_lang_item(LangItem::Copy, None); let code = traits::ObligationCauseCode::RepeatElementCopy { is_constable, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index e20a6ef7c1339..172d874d4eed7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2240,7 +2240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (idx, (generic_param, param)) in params_with_generics.iter().enumerate().filter(|(idx, _)| { check_for_matched_generics - || expected_idx.map_or(true, |expected_idx| expected_idx == *idx) + || expected_idx.is_none_or(|expected_idx| expected_idx == *idx) }) { let Some(generic_param) = generic_param else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 9ab89f3444c9c..8a88e5a6ff489 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -440,7 +440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for // `as_ref` and `as_deref` compatibility. - let error_tys_equate_as_ref = error_tys.map_or(true, |(found, expected)| { + let error_tys_equate_as_ref = error_tys.is_none_or(|(found, expected)| { self.can_eq( self.param_env, Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, found), @@ -492,7 +492,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && Some(adt.did()) == self.tcx.lang_items().string() && peeled.is_str() // `Result::map`, conversely, does not take ref of the error type. - && error_tys.map_or(true, |(found, expected)| { + && error_tys.is_none_or(|(found, expected)| { self.can_eq(self.param_env, found, expected) }) { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index b0fd6de349680..a87ee7b455488 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -4,6 +4,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(if_let_guard)] +#![feature(is_none_or)] #![feature(let_chains)] #![feature(never_type)] #![feature(try_blocks)] diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index effb4090692cc..bc59b5e033baa 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -546,7 +546,7 @@ impl Trait for X { for pred in hir_generics.bounds_for_param(def_id) { if self.constrain_generic_bound_associated_type_structured_suggestion( diag, - &trait_ref, + trait_ref, pred.bounds, assoc, assoc_args, @@ -715,7 +715,7 @@ fn foo(&self) -> Self::T { String::new() } self.constrain_generic_bound_associated_type_structured_suggestion( diag, - &trait_ref, + trait_ref, opaque_hir_ty.bounds, assoc, assoc_args, @@ -869,7 +869,7 @@ fn foo(&self) -> Self::T { String::new() } fn constrain_generic_bound_associated_type_structured_suggestion( &self, diag: &mut Diag<'_>, - trait_ref: &ty::TraitRef<'tcx>, + trait_ref: ty::TraitRef<'tcx>, bounds: hir::GenericBounds<'_>, assoc: ty::AssocItem, assoc_args: &[ty::GenericArg<'tcx>], diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs index e7b50479b850c..41cc945492daf 100644 --- a/compiler/rustc_infer/src/infer/relate/mod.rs +++ b/compiler/rustc_infer/src/infer/relate/mod.rs @@ -4,11 +4,9 @@ pub use rustc_middle::ty::relate::*; -pub use self::_match::MatchAgainstFreshVars; pub use self::combine::CombineFields; pub use self::combine::PredicateEmittingRelation; -pub mod _match; pub(super) mod combine; mod generalize; mod glb; diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index cc12a4bf09146..ab4148faaab63 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -285,8 +285,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { let obligations = predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| { elaboratable.child_with_derived_cause( - clause - .instantiate_supertrait(tcx, &bound_clause.rebind(data.trait_ref)), + clause.instantiate_supertrait(tcx, bound_clause.rebind(data.trait_ref)), span, bound_clause.rebind(data), index, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 726bd0de1299f..45051394ffca3 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3257,7 +3257,11 @@ declare_lint! { /// See the [Checking Conditional Configurations][check-cfg] section for more /// details. /// + /// See the [Cargo Specifics][unexpected_cfgs_lint_config] section for configuring this lint in + /// `Cargo.toml`. + /// /// [check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html + /// [unexpected_cfgs_lint_config]: https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html#check-cfg-in-lintsrust-table pub UNEXPECTED_CFGS, Warn, "detects unexpected names and values in `#[cfg]` conditions", diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index 707e076921bce..adbb6cf2ddc94 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -37,7 +37,7 @@ impl<'tcx> Elaborator<'tcx> { let super_predicates = self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map( |&(pred, _)| { - let clause = pred.instantiate_supertrait(self.tcx, &trait_ref); + let clause = pred.instantiate_supertrait(self.tcx, trait_ref); self.visited.insert(clause).then_some(clause) }, ); diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index c730f5117c561..785aa8d456fc6 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -313,7 +313,7 @@ impl<'tcx> Clause<'tcx> { pub fn instantiate_supertrait( self, tcx: TyCtxt<'tcx>, - trait_ref: &ty::PolyTraitRef<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, ) -> Clause<'tcx> { // The interaction between HRTB and supertraits is not entirely // obvious. Let me walk you (and myself) through an example. diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs index 4d7e2fc2cefab..59a8de99b8f6d 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs @@ -48,6 +48,12 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { rhs }; + // Add a `make_canonical_response` probe step so that we treat this as + // a candidate, even if `try_evaluate_added_goals` bails due to an error. + // It's `Certainty::AMBIGUOUS` because this candidate is not "finished", + // since equating the normalized terms will lead to additional constraints. + self.inspect.make_canonical_response(Certainty::AMBIGUOUS); + // Apply the constraints. self.try_evaluate_added_goals()?; let lhs = self.resolve_vars_if_possible(lhs); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index dc13941e5d7b5..3c3d5dfe79c49 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -460,9 +460,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { polarity: ty::PredicatePolarity::Positive, })) } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => { - ChildMode::WellFormedObligation - } + ty::PredicateKind::Clause( + ty::ClauseKind::WellFormed(_) | ty::ClauseKind::Projection(..), + ) + | ty::PredicateKind::AliasRelate(..) => ChildMode::PassThrough, _ => { return ControlFlow::Break(self.obligation.clone()); } @@ -496,7 +497,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { (_, GoalSource::InstantiateHigherRanked) => { obligation = self.obligation.clone(); } - (ChildMode::WellFormedObligation, _) => { + (ChildMode::PassThrough, _) => { obligation = make_obligation(self.obligation.cause.clone()); } } @@ -527,7 +528,7 @@ enum ChildMode<'tcx> { // Skip trying to derive an `ObligationCause` from this obligation, and // report *all* sub-obligations as if they came directly from the parent // obligation. - WellFormedObligation, + PassThrough, } fn derive_cause<'tcx>( diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 19c95dad48cb5..b9c98b6a2e96d 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -15,7 +15,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_macros::extension; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{inspect, QueryResult}; -use rustc_middle::traits::solve::{Certainty, Goal}; +use rustc_middle::traits::solve::{Certainty, Goal, MaybeCause}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{TyCtxt, TypeFoldable}; use rustc_middle::{bug, ty}; @@ -291,7 +291,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { steps.push(step) } inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { - assert_eq!(shallow_certainty.replace(c), None); + assert!(matches!( + shallow_certainty.replace(c), + None | Some(Certainty::Maybe(MaybeCause::Ambiguity)) + )); } inspect::ProbeStep::NestedProbe(ref probe) => { match probe.kind { 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 087f7fbea00b3..4604c132835b2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3597,7 +3597,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut Diag<'_>, - trait_ref: &ty::PolyTraitRef<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, ) { let rhs_span = match obligation.cause.code() { ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => { @@ -4592,7 +4592,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut Diag<'_>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) { if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() { return; @@ -4602,10 +4602,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let hir::Node::Item(item) = node && let hir::ItemKind::Fn(sig, _, body_id) = item.kind && let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output - && self.tcx.is_diagnostic_item(sym::FromResidual, trait_ref.def_id()) - && let ty::Tuple(l) = trait_ref.skip_binder().args.type_at(0).kind() - && l.len() == 0 - && let ty::Adt(def, _) = trait_ref.skip_binder().args.type_at(1).kind() + && self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id()) + && trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit() + && let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind() && self.tcx.is_diagnostic_item(sym::Result, def.did()) { let body = self.tcx.hir().body(body_id); @@ -4863,14 +4862,13 @@ impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> { pub(super) fn get_explanation_based_on_obligation<'tcx>( tcx: TyCtxt<'tcx>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, + trait_predicate: ty::PolyTraitPredicate<'tcx>, pre_message: String, ) -> String { if let ObligationCauseCode::MainFunctionType = obligation.cause.code() { "consider using `()`, or a `Result`".to_owned() } else { - let ty_desc = match trait_ref.skip_binder().self_ty().kind() { + let ty_desc = match trait_predicate.self_ty().skip_binder().kind() { ty::FnDef(_, _) => Some("fn item"), ty::Closure(_, _) => Some("closure"), _ => None, @@ -4895,7 +4893,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>( format!( "{pre_message}the trait `{}` is not implemented for{desc} `{}`{post}", trait_predicate.print_modifiers_and_trait_path(), - tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None), + tcx.short_ty_string(trait_predicate.self_ty().skip_binder(), &mut None), ) } else { // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 6b6438a7887e5..aef9d482bec74 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -412,8 +412,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let bound_predicate = obligation.predicate.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { - let trait_predicate = bound_predicate.rebind(trait_predicate); - let trait_predicate = self.resolve_vars_if_possible(trait_predicate); + let leaf_trait_predicate = + self.resolve_vars_if_possible(bound_predicate.rebind(trait_predicate)); // Let's use the root obligation as the main message, when we care about the // most general case ("X doesn't implement Pattern<'_>") over the case that @@ -424,7 +424,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let (main_trait_predicate, o) = if let ty::PredicateKind::Clause( ty::ClauseKind::Trait(root_pred) ) = root_obligation.predicate.kind().skip_binder() - && !trait_predicate.self_ty().skip_binder().has_escaping_bound_vars() + && !leaf_trait_predicate.self_ty().skip_binder().has_escaping_bound_vars() && !root_pred.self_ty().has_escaping_bound_vars() // The type of the leaf predicate is (roughly) the same as the type // from the root predicate, as a proxy for "we care about the root" @@ -434,20 +434,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait` self.can_eq( obligation.param_env, - trait_predicate.self_ty().skip_binder(), + leaf_trait_predicate.self_ty().skip_binder(), root_pred.self_ty().peel_refs(), ) // `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator` || self.can_eq( obligation.param_env, - trait_predicate.self_ty().skip_binder(), + leaf_trait_predicate.self_ty().skip_binder(), root_pred.self_ty(), ) ) // The leaf trait and the root trait are different, so as to avoid // talking about `&mut T: Trait` and instead remain talking about // `T: Trait` instead - && trait_predicate.def_id() != root_pred.def_id() + && leaf_trait_predicate.def_id() != root_pred.def_id() // The root trait is not `Unsize`, as to avoid talking about it in // `tests/ui/coercion/coerce-issue-49593-box-never.rs`. && Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait() @@ -459,13 +459,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { root_obligation, ) } else { - (trait_predicate, &obligation) + (leaf_trait_predicate, &obligation) }; - let trait_ref = main_trait_predicate.to_poly_trait_ref(); + let main_trait_ref = main_trait_predicate.to_poly_trait_ref(); + let leaf_trait_ref = leaf_trait_predicate.to_poly_trait_ref(); if let Some(guar) = self.emit_specialized_closure_kind_error( &obligation, - trait_ref, + leaf_trait_ref, ) { return guar; } @@ -473,7 +474,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // FIXME(effects) let predicate_is_const = false; - if let Err(guar) = trait_predicate.error_reported() + if let Err(guar) = leaf_trait_predicate.error_reported() { return guar; } @@ -507,16 +508,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { notes, parent_label, append_const_msg, - } = self.on_unimplemented_note(trait_ref, o, &mut long_ty_file); + } = self.on_unimplemented_note(main_trait_ref, o, &mut long_ty_file); + let have_alt_message = message.is_some() || label.is_some(); - let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); + let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id()); let is_unsize = - Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); + Some(leaf_trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); let (message, notes, append_const_msg) = if is_try_conversion { ( Some(format!( "`?` couldn't convert the error to `{}`", - trait_ref.skip_binder().self_ty(), + main_trait_ref.skip_binder().self_ty(), )), vec![ "the question mark operation (`?`) implicitly performs a \ @@ -530,20 +532,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }; let err_msg = self.get_standard_error_message( - &main_trait_predicate, + main_trait_predicate, message, predicate_is_const, append_const_msg, post_message, ); - let (err_msg, safe_transmute_explanation) = if Some(trait_ref.def_id()) + let (err_msg, safe_transmute_explanation) = if Some(main_trait_ref.def_id()) == self.tcx.lang_items().transmute_trait() { // Recompute the safe transmute reason and use that for the error reporting match self.get_safe_transmute_error_and_reason( obligation.clone(), - trait_ref, + main_trait_ref, span, ) { GetSafeTransmuteErrorAndReason::Silent => { @@ -571,7 +573,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } let mut suggested = false; if is_try_conversion { - suggested = self.try_conversion_context(&obligation, trait_ref.skip_binder(), &mut err); + suggested = self.try_conversion_context(&obligation, main_trait_ref.skip_binder(), &mut err); } if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) { @@ -579,19 +581,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ret_span, format!( "expected `{}` because of this", - trait_ref.skip_binder().self_ty() + main_trait_ref.skip_binder().self_ty() ), ); } - if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() { + if Some(leaf_trait_ref.def_id()) == tcx.lang_items().tuple_trait() { self.add_tuple_trait_message( obligation.cause.code().peel_derives(), &mut err, ); } - if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait() + if Some(leaf_trait_ref.def_id()) == tcx.lang_items().drop_trait() && predicate_is_const { err.note("`~const Drop` was renamed to `~const Destruct`"); @@ -601,24 +603,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let explanation = get_explanation_based_on_obligation( self.tcx, &obligation, - trait_ref, - &trait_predicate, + leaf_trait_predicate, pre_message, ); self.check_for_binding_assigned_block_without_tail_expression( &obligation, &mut err, - trait_predicate, + leaf_trait_predicate, ); - self.suggest_add_result_as_return_type(&obligation, + self.suggest_add_result_as_return_type( + &obligation, &mut err, - trait_ref); + leaf_trait_predicate, + ); if self.suggest_add_reference_to_arg( &obligation, &mut err, - trait_predicate, + leaf_trait_predicate, have_alt_message, ) { self.note_obligation_cause(&mut err, &obligation); @@ -630,7 +633,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // If it has a custom `#[rustc_on_unimplemented]` // error message, let's display it as the label! err.span_label(span, s); - if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { + if !matches!(leaf_trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { // When the self type is a type param We don't need to "the trait // `std::marker::Sized` is not implemented for `T`" as we will point // at the type param with a label to suggest constraining it. @@ -645,7 +648,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let ObligationCauseCode::Coercion { source, target } = *obligation.cause.code().peel_derives() { - if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { + if Some(leaf_trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { self.suggest_borrowing_for_object_cast( &mut err, root_obligation, @@ -657,7 +660,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let UnsatisfiedConst(unsatisfied_const) = self .maybe_add_note_for_unsatisfied_const( - &trait_predicate, + leaf_trait_predicate, &mut err, span, ); @@ -674,15 +677,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.span_label(tcx.def_span(body), s); } - self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref); - self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate); - suggested |= self.suggest_dereferences(&obligation, &mut err, trait_predicate); - suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); - let impl_candidates = self.find_similar_impl_candidates(trait_predicate); + self.suggest_floating_point_literal(&obligation, &mut err, leaf_trait_ref); + self.suggest_dereferencing_index(&obligation, &mut err, leaf_trait_predicate); + suggested |= self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate); + suggested |= self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate); + let impl_candidates = self.find_similar_impl_candidates(leaf_trait_predicate); suggested = if let &[cand] = &impl_candidates[..] { let cand = cand.trait_ref; if let (ty::FnPtr(_), ty::FnDef(..)) = - (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) + (cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind()) { err.span_suggestion( span.shrink_to_hi(), @@ -702,31 +705,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { false } || suggested; suggested |= - self.suggest_remove_reference(&obligation, &mut err, trait_predicate); + self.suggest_remove_reference(&obligation, &mut err, leaf_trait_predicate); suggested |= self.suggest_semicolon_removal( &obligation, &mut err, span, - trait_predicate, + leaf_trait_predicate, ); - self.note_version_mismatch(&mut err, &trait_ref); + self.note_version_mismatch(&mut err, leaf_trait_ref); self.suggest_remove_await(&obligation, &mut err); - self.suggest_derive(&obligation, &mut err, trait_predicate); + self.suggest_derive(&obligation, &mut err, leaf_trait_predicate); - if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { + if Some(leaf_trait_ref.def_id()) == tcx.lang_items().try_trait() { self.suggest_await_before_try( &mut err, &obligation, - trait_predicate, + leaf_trait_predicate, span, ); } - if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) { + if self.suggest_add_clone_to_arg(&obligation, &mut err, leaf_trait_predicate) { return err.emit(); } - if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) { + if self.suggest_impl_trait(&mut err, &obligation, leaf_trait_predicate) { return err.emit(); } @@ -741,9 +744,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); } - let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id()); + let is_fn_trait = tcx.is_fn_trait(leaf_trait_ref.def_id()); let is_target_feature_fn = if let ty::FnDef(def_id, _) = - *trait_ref.skip_binder().self_ty().kind() + *leaf_trait_ref.skip_binder().self_ty().kind() { !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() } else { @@ -757,8 +760,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.try_to_add_help_message( &obligation, - trait_ref, - &trait_predicate, + leaf_trait_predicate, &mut err, span, is_fn_trait, @@ -769,17 +771,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // Changing mutability doesn't make a difference to whether we have // an `Unsize` impl (Fixes ICE in #71036) if !is_unsize { - self.suggest_change_mut(&obligation, &mut err, trait_predicate); + self.suggest_change_mut(&obligation, &mut err, leaf_trait_predicate); } // If this error is due to `!: Trait` not implemented but `(): Trait` is // implemented, and fallback has occurred, then it could be due to a // variable that used to fallback to `()` now falling back to `!`. Issue a // note informing about the change in behaviour. - if trait_predicate.skip_binder().self_ty().is_never() + if leaf_trait_predicate.skip_binder().self_ty().is_never() && self.fallback_has_occurred { - let predicate = trait_predicate.map_bound(|trait_pred| { + let predicate = leaf_trait_predicate.map_bound(|trait_pred| { trait_pred.with_self_ty(self.tcx, tcx.types.unit) }); let unit_obligation = obligation.with(tcx, predicate); @@ -794,8 +796,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - self.explain_hrtb_projection(&mut err, trait_predicate, obligation.param_env, &obligation.cause); - self.suggest_desugaring_async_fn_in_trait(&mut err, trait_ref); + self.explain_hrtb_projection(&mut err, leaf_trait_predicate, obligation.param_env, &obligation.cause); + self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_ref); // Return early if the trait is Debug or Display and the invocation // originates within a standard library macro, because the output @@ -813,15 +815,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if in_std_macro && matches!( - self.tcx.get_diagnostic_name(trait_ref.def_id()), + self.tcx.get_diagnostic_name(leaf_trait_ref.def_id()), Some(sym::Debug | sym::Display) ) { return err.emit(); } - - err } @@ -2236,11 +2236,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait /// with the same path as `trait_ref`, a help message about /// a probable version mismatch is added to `err` - fn note_version_mismatch( - &self, - err: &mut Diag<'_>, - trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> bool { + fn note_version_mismatch(&self, err: &mut Diag<'_>, trait_ref: ty::PolyTraitRef<'tcx>) -> bool { let get_trait_impls = |trait_def_id| { let mut trait_impls = vec![]; self.tcx.for_each_relevant_impl( @@ -2705,6 +2701,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ), ); } + + ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) + if term.is_infer() => + { + if let Some(e) = self.tainted_by_errors() { + return e; + } + struct_span_code_err!( + self.dcx(), + span, + E0284, + "type annotations needed: cannot normalize `{alias}`", + ) + .with_span_label(span, format!("cannot normalize `{alias}`")) + } + _ => { if let Some(e) = self.tainted_by_errors() { return e; @@ -3044,7 +3056,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn get_standard_error_message( &self, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, + trait_predicate: ty::PolyTraitPredicate<'tcx>, message: Option, predicate_is_const: bool, append_const_msg: Option, @@ -3215,8 +3227,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn try_to_add_help_message( &self, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, + trait_predicate: ty::PolyTraitPredicate<'tcx>, err: &mut Diag<'_>, span: Span, is_fn_trait: bool, @@ -3233,16 +3244,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }; // Try to report a help message + let trait_def_id = trait_predicate.def_id(); if is_fn_trait && let Ok((implemented_kind, params)) = self.type_implements_fn_trait( obligation.param_env, - trait_ref.self_ty(), + trait_predicate.self_ty(), trait_predicate.skip_binder().polarity, ) { - self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params); - } else if !trait_ref.has_non_region_infer() - && self.predicate_can_apply(obligation.param_env, *trait_predicate) + self.add_help_message_for_fn_trait( + trait_predicate.to_poly_trait_ref(), + err, + implemented_kind, + params, + ); + } else if !trait_predicate.has_non_region_infer() + && self.predicate_can_apply(obligation.param_env, trait_predicate) { // If a where-clause may be useful, remind the // user that they can add it. @@ -3253,25 +3270,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // which is somewhat confusing. self.suggest_restricting_param_bound( err, - *trait_predicate, + trait_predicate, None, obligation.cause.body_id, ); - } else if trait_ref.def_id().is_local() - && self.tcx.trait_impls_of(trait_ref.def_id()).is_empty() - && !self.tcx.trait_is_auto(trait_ref.def_id()) - && !self.tcx.trait_is_alias(trait_ref.def_id()) + } else if trait_def_id.is_local() + && self.tcx.trait_impls_of(trait_def_id).is_empty() + && !self.tcx.trait_is_auto(trait_def_id) + && !self.tcx.trait_is_alias(trait_def_id) { err.span_help( - self.tcx.def_span(trait_ref.def_id()), + self.tcx.def_span(trait_def_id), crate::fluent_generated::trait_selection_trait_has_no_impls, ); } else if !suggested && !unsatisfied_const { // Can't show anything else useful, try to find similar impls. - let impl_candidates = self.find_similar_impl_candidates(*trait_predicate); + let impl_candidates = self.find_similar_impl_candidates(trait_predicate); if !self.report_similar_impl_candidates( &impl_candidates, - trait_ref, + trait_predicate.to_poly_trait_ref(), body_def_id, err, true, @@ -3279,7 +3296,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) { self.report_similar_impl_candidates_for_root_obligation( obligation, - *trait_predicate, + trait_predicate, body_def_id, err, ); @@ -3288,7 +3305,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.suggest_convert_to_slice( err, obligation, - trait_ref, + trait_predicate.to_poly_trait_ref(), impl_candidates.as_slice(), span, ); @@ -3353,7 +3370,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn maybe_add_note_for_unsatisfied_const( &self, - _trait_predicate: &ty::PolyTraitPredicate<'tcx>, + _trait_predicate: ty::PolyTraitPredicate<'tcx>, _err: &mut Diag<'_>, _span: Span, ) -> UnsatisfiedConst { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 08355ef55c492..fc5a2875b67ad 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -194,7 +194,7 @@ fn predicates_reference_self( predicates .predicates .iter() - .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, &trait_ref), sp)) + .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp)) .filter_map(|predicate| predicate_references_self(tcx, predicate)) .collect() } diff --git a/compiler/rustc_infer/src/infer/relate/_match.rs b/compiler/rustc_trait_selection/src/traits/select/_match.rs similarity index 97% rename from compiler/rustc_infer/src/infer/relate/_match.rs rename to compiler/rustc_trait_selection/src/traits/select/_match.rs index 30a066a265acd..50d8e96aaf91f 100644 --- a/compiler/rustc_infer/src/infer/relate/_match.rs +++ b/compiler/rustc_trait_selection/src/traits/select/_match.rs @@ -1,10 +1,10 @@ +use rustc_infer::infer::relate::{ + self, structurally_relate_tys, Relate, RelateResult, TypeRelation, +}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; use tracing::{debug, instrument}; -use super::{structurally_relate_tys, Relate, RelateResult, TypeRelation}; -use crate::infer::relate; - /// A type "A" *matches* "B" if the fresh types in B could be /// instantiated with values so as to make it equal to A. Matching is /// intended to be used only on freshened types, and it basically diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4306a8035241a..212ef2e4b2beb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -32,7 +32,6 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_infer::infer::relate::MatchAgainstFreshVars; use rustc_infer::infer::relate::TypeRelation; use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType; @@ -60,6 +59,7 @@ use std::ops::ControlFlow; pub use rustc_middle::traits::select::*; use rustc_middle::ty::print::with_no_trimmed_paths; +mod _match; mod candidate_assembly; mod confirmation; @@ -1866,7 +1866,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. let is_global = - |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars(); + |cand: ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars(); // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // `DiscriminantKindCandidate`, `ConstDestructCandidate` @@ -1909,7 +1909,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } ( - ParamCandidate(ref other_cand), + ParamCandidate(other_cand), ImplCandidate(..) | AutoImplCandidate | ClosureCandidate { .. } @@ -1934,12 +1934,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // // Global bounds from the where clause should be ignored // here (see issue #50825). - DropVictim::drop_if(!is_global(other_cand)) + DropVictim::drop_if(!is_global(*other_cand)) } - (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => { + (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(victim_cand)) => { // Prefer these to a global where-clause bound // (see issue #50825). - if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No } + if is_global(*victim_cand) { DropVictim::Yes } else { DropVictim::No } } ( ImplCandidate(_) @@ -1957,12 +1957,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | TraitUpcastingUnsizeCandidate(_) | BuiltinCandidate { has_nested: true } | TraitAliasCandidate, - ParamCandidate(ref victim_cand), + ParamCandidate(victim_cand), ) => { // Prefer these to a global where-clause bound // (see issue #50825). DropVictim::drop_if( - is_global(victim_cand) && other.evaluation.must_apply_modulo_regions(), + is_global(*victim_cand) && other.evaluation.must_apply_modulo_regions(), ) } @@ -2719,7 +2719,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { previous: ty::PolyTraitPredicate<'tcx>, current: ty::PolyTraitPredicate<'tcx>, ) -> bool { - let mut matcher = MatchAgainstFreshVars::new(self.tcx()); + let mut matcher = _match::MatchAgainstFreshVars::new(self.tcx()); matcher.relate(previous, current).is_ok() } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 960c27b636e12..ce7245d93a4e4 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -132,7 +132,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { debug!(?predicates); let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { - pred.instantiate_supertrait(tcx, &trait_ref) + pred.instantiate_supertrait(tcx, trait_ref) .as_trait_clause() .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) }); diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index c93ec43944ad2..9bd4a9aab0ab5 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -125,7 +125,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( .predicates .into_iter() .filter_map(move |(pred, _)| { - pred.instantiate_supertrait(tcx, &inner_most_trait_ref).as_trait_clause() + pred.instantiate_supertrait(tcx, inner_most_trait_ref).as_trait_clause() }); // Find an unvisited supertrait diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index eae1a9dfaa2c2..241381f5875ed 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -331,30 +331,63 @@ pub(crate) mod rustc { assert!(def.is_enum()); let layout = ty_and_layout.layout; - if let Variants::Multiple { tag_field, .. } = layout.variants() { - // For enums (but not coroutines), the tag field is - // currently always the first field of the layout. - assert_eq!(*tag_field, 0); - } + // Computes the variant of a given index. + let layout_of_variant = |index| { + let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, index)); + let variant_def = Def::Variant(def.variant(index)); + let variant_ty_and_layout = ty_and_layout.for_variant(&cx, index); + Self::from_variant(variant_def, tag, variant_ty_and_layout, layout.size, cx) + }; - let variants = def.discriminants(cx.tcx()).try_fold( - Self::uninhabited(), - |variants, (idx, ref discriminant)| { - let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, idx)); - let variant_def = Def::Variant(def.variant(idx)); - let variant_ty_and_layout = ty_and_layout.for_variant(&cx, idx); - let variant = Self::from_variant( - variant_def, - tag, - variant_ty_and_layout, - layout.size, - cx, + // We consider three kinds of enums, each demanding a different + // treatment of their layout computation: + // 1. enums that are uninhabited + // 2. enums for which all but one variant is uninhabited + // 3. enums with multiple inhabited variants + match layout.variants() { + _ if layout.abi.is_uninhabited() => { + // Uninhabited enums are usually (always?) zero-sized. In + // the (unlikely?) event that an uninhabited enum is + // non-zero-sized, this assert will trigger an ICE, and this + // code should be modified such that a `layout.size` amount + // of uninhabited bytes is returned instead. + // + // Uninhabited enums are currently implemented such that + // their layout is described with `Variants::Single`, even + // though they don't necessarily have a 'single' variant to + // defer to. That said, we don't bother specifically + // matching on `Variants::Single` in this arm because the + // behavioral principles here remain true even if, for + // whatever reason, the compiler describes an uninhabited + // enum with `Variants::Multiple`. + assert_eq!(layout.size, Size::ZERO); + Ok(Self::uninhabited()) + } + Variants::Single { index } => { + // `Variants::Single` on non-uninhabited enums denotes that + // the enum delegates its layout to the variant at `index`. + layout_of_variant(*index) + } + Variants::Multiple { tag_field, .. } => { + // `Variants::Multiple` denotes an enum with multiple + // inhabited variants. The layout of such an enum is the + // disjunction of the layouts of its tagged variants. + + // For enums (but not coroutines), the tag field is + // currently always the first field of the layout. + assert_eq!(*tag_field, 0); + + let variants = def.discriminants(cx.tcx()).try_fold( + Self::uninhabited(), + |variants, (idx, ref discriminant)| { + let variant = layout_of_variant(idx)?; + Result::::Ok(variants.or(variant)) + }, )?; - Result::::Ok(variants.or(variant)) - }, - )?; - return Ok(Self::def(Def::Adt(def)).then(variants)); + return Ok(Self::def(Def::Adt(def)).then(variants)); + } + } } /// Constructs a `Tree` from a 'variant-like' layout. diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index bcbe87f7303b3..8c9824f8f8df8 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -122,7 +122,7 @@ impl TyConst { } /// Creates an interned usize constant. - fn try_from_target_usize(val: u64) -> Result { + pub fn try_from_target_usize(val: u64) -> Result { with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize)) } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 8ac2a8bb17f41..403fe4ff04c53 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -654,6 +654,32 @@ impl Option { !self.is_some() } + /// Returns `true` if the option is a [`None`] or the value inside of it matches a predicate. + /// + /// # Examples + /// + /// ``` + /// #![feature(is_none_or)] + /// + /// let x: Option = Some(2); + /// assert_eq!(x.is_none_or(|x| x > 1), true); + /// + /// let x: Option = Some(0); + /// assert_eq!(x.is_none_or(|x| x > 1), false); + /// + /// let x: Option = None; + /// assert_eq!(x.is_none_or(|x| x > 1), true); + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "is_none_or", issue = "none")] + pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool { + match self { + None => true, + Some(x) => f(x), + } + } + ///////////////////////////////////////////////////////////////////////// // Adapter for working with references ///////////////////////////////////////////////////////////////////////// diff --git a/src/doc/rustc/src/check-cfg.md b/src/doc/rustc/src/check-cfg.md index 8e39adaa43858..dfc4871b924d4 100644 --- a/src/doc/rustc/src/check-cfg.md +++ b/src/doc/rustc/src/check-cfg.md @@ -11,8 +11,8 @@ development process. In order to accomplish that goal, `rustc` accepts the `--check-cfg` flag, which specifies whether to check conditions and how to check them. -> **Note:** No implicit expectation is added when using `--cfg`. Users are expected to -pass all expected names and values using the _check cfg specification_. +> **Note:** For interacting with this through Cargo, +see [Cargo Specifics](check-cfg/cargo-specifics.md) page. [^reachable]: `rustc` promises to at least check reachable `#[cfg]`, and while non-reachable `#[cfg]` are not currently checked, they may well be checked in the future without it being a @@ -23,6 +23,9 @@ breaking change. To specify expected names and values, the _check cfg specification_ provides the `cfg(...)` option which enables specifying for an expected config name and it's expected values. +> **Note:** No implicit expectation is added when using `--cfg`. Users are expected to +pass all expected names and values using the _check cfg specification_. + It has this basic form: ```bash diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 11cbbde06aa08..f8410db4dd0f9 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -13,6 +13,7 @@ #![feature(lint_reasons)] #![feature(trait_upcasting)] #![feature(strict_overflow_ops)] +#![feature(is_none_or)] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 898fc111fd43f..911958e558c5a 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -396,12 +396,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // If the newly promised alignment is bigger than the native alignment of this // allocation, and bigger than the previously promised alignment, then set it. if align > alloc_align - && !this + && this .machine .symbolic_alignment .get_mut() .get(&alloc_id) - .is_some_and(|&(_, old_align)| align <= old_align) + .is_none_or(|&(_, old_align)| align > old_align) { this.machine.symbolic_alignment.get_mut().insert(alloc_id, (offset, align)); } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index b7a936a1e115d..0238255a53f3a 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -95,6 +95,34 @@ pub fn source_root() -> PathBuf { env_var("SOURCE_ROOT").into() } +/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix. +#[cfg(target_family = "windows")] +pub fn create_symlink, Q: AsRef>(original: P, link: Q) { + if link.as_ref().exists() { + std::fs::remove_dir(link.as_ref()).unwrap(); + } + use std::os::windows::fs; + fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!( + "failed to create symlink {:?} for {:?}", + link.as_ref().display(), + original.as_ref().display(), + )); +} + +/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix. +#[cfg(target_family = "unix")] +pub fn create_symlink, Q: AsRef>(original: P, link: Q) { + if link.as_ref().exists() { + std::fs::remove_dir(link.as_ref()).unwrap(); + } + use std::os::unix::fs; + fs::symlink(original.as_ref(), link.as_ref()).expect(&format!( + "failed to create symlink {:?} for {:?}", + link.as_ref().display(), + original.as_ref().display(), + )); +} + /// Construct the static library name based on the platform. pub fn static_lib_name(name: &str) -> String { // See tools.mk (irrelevant lines omitted): diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 5a9621bb69a47..241690d00896d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -1387,6 +1387,7 @@ fn generic_args_sans_defaults<'ga>( } // otherwise, if the arg is equal to the param default, hide it (unless the // default is an error which can happen for the trait Self type) + #[allow(unstable_name_collisions)] default_parameters.get(i).is_none_or(|default_parameter| { // !is_err(default_parameter.skip_binders()) // && diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index d4c3a970c70ec..37da5d9c88d90 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -226,9 +226,6 @@ run-make/std-core-cycle/Makefile run-make/symbol-mangling-hashed/Makefile run-make/symbol-visibility/Makefile run-make/symbols-include-type-name/Makefile -run-make/symlinked-extern/Makefile -run-make/symlinked-libraries/Makefile -run-make/symlinked-rlib/Makefile run-make/sysroot-crates-are-unstable/Makefile run-make/target-cpu-native/Makefile run-make/target-specs/Makefile diff --git a/tests/crashes/125811.rs b/tests/crashes/125811.rs deleted file mode 100644 index eb764e8d15228..0000000000000 --- a/tests/crashes/125811.rs +++ /dev/null @@ -1,34 +0,0 @@ -//@ known-bug: rust-lang/rust#125811 -mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; - - pub fn is_transmutable() - where - Dst: BikeshedIntrinsicFrom, - { - } -} - -#[repr(C)] -struct Zst; - -enum V0 { - B(!), -} - -enum V2 { - V = 2, -} - -enum Lopsided { - Smol(Zst), - Lorg(V0), -} - -#[repr(C)] -#[repr(C)] -struct Dst(Lopsided, V2); - -fn should_pad_variants() { - assert::is_transmutable::(); -} diff --git a/tests/run-make/symlinked-extern/Makefile b/tests/run-make/symlinked-extern/Makefile deleted file mode 100644 index 28c764b84e8b7..0000000000000 --- a/tests/run-make/symlinked-extern/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# ignore-windows -# `ln` is actually `cp` on msys. - -all: - $(RUSTC) foo.rs - mkdir -p $(TMPDIR)/other - ln -nsf $(TMPDIR)/libfoo.rlib $(TMPDIR)/other - $(RUSTC) bar.rs -L $(TMPDIR) - $(RUSTC) baz.rs --extern foo=$(TMPDIR)/other/libfoo.rlib -L $(TMPDIR) diff --git a/tests/run-make/symlinked-extern/rmake.rs b/tests/run-make/symlinked-extern/rmake.rs new file mode 100644 index 0000000000000..98f69aefbe622 --- /dev/null +++ b/tests/run-make/symlinked-extern/rmake.rs @@ -0,0 +1,21 @@ +// Crates that are resolved normally have their path canonicalized and all +// symlinks resolved. This did not happen for paths specified +// using the --extern option to rustc, which could lead to rustc thinking +// that it encountered two different versions of a crate, when it's +// actually the same version found through different paths. +// See https://github.com/rust-lang/rust/pull/16505 + +// This test checks that --extern and symlinks together +// can result in successful compilation. + +//@ ignore-cross-compile + +use run_make_support::{create_symlink, cwd, fs_wrapper, rustc}; + +fn main() { + rustc().input("foo.rs").run(); + fs_wrapper::create_dir_all("other"); + create_symlink("libfoo.rlib", "other"); + rustc().input("bar.rs").library_search_path(cwd()).run(); + rustc().input("baz.rs").extern_("foo", "other").library_search_path(cwd()).run(); +} diff --git a/tests/run-make/symlinked-libraries/Makefile b/tests/run-make/symlinked-libraries/Makefile deleted file mode 100644 index fb0b6127e6f5c..0000000000000 --- a/tests/run-make/symlinked-libraries/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# ignore-windows -# `ln` is actually `cp` on msys. - -all: - $(RUSTC) foo.rs -C prefer-dynamic - mkdir -p $(TMPDIR)/other - ln -nsf $(TMPDIR)/$(call DYLIB_GLOB,foo) $(TMPDIR)/other - $(RUSTC) bar.rs -L $(TMPDIR)/other diff --git a/tests/run-make/symlinked-libraries/rmake.rs b/tests/run-make/symlinked-libraries/rmake.rs new file mode 100644 index 0000000000000..eaf0c44206a5f --- /dev/null +++ b/tests/run-make/symlinked-libraries/rmake.rs @@ -0,0 +1,16 @@ +// When a directory and a symlink simultaneously exist with the same name, +// setting that name as the library search path should not cause rustc +// to avoid looking in the symlink and cause an error. This test creates +// a directory and a symlink named "other", and places the library in the symlink. +// If it succeeds, the library was successfully found. +// See https://github.com/rust-lang/rust/issues/12459 + +//@ ignore-cross-compile +use run_make_support::{create_symlink, dynamic_lib_name, fs_wrapper, rustc}; + +fn main() { + rustc().input("foo.rs").arg("-Cprefer-dynamic").run(); + fs_wrapper::create_dir_all("other"); + create_symlink(dynamic_lib_name("foo"), "other"); + rustc().input("bar.rs").library_search_path("other").run(); +} diff --git a/tests/run-make/symlinked-rlib/Makefile b/tests/run-make/symlinked-rlib/Makefile deleted file mode 100644 index a8565f683c3e8..0000000000000 --- a/tests/run-make/symlinked-rlib/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# ignore-windows -# `ln` is actually `cp` on msys. - -all: - $(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo.xxx - ln -nsf $(TMPDIR)/foo.xxx $(TMPDIR)/libfoo.rlib - $(RUSTC) bar.rs -L $(TMPDIR) diff --git a/tests/run-make/symlinked-rlib/rmake.rs b/tests/run-make/symlinked-rlib/rmake.rs new file mode 100644 index 0000000000000..3759ca25928a1 --- /dev/null +++ b/tests/run-make/symlinked-rlib/rmake.rs @@ -0,0 +1,16 @@ +// Rustc did not recognize libraries which were symlinked +// to files having extension other than .rlib. This was fixed +// in #32828. This test creates a symlink to "foo.xxx", which has +// an unusual file extension, and checks that rustc can successfully +// use it as an rlib library. +// See https://github.com/rust-lang/rust/pull/32828 + +//@ ignore-cross-compile + +use run_make_support::{create_symlink, cwd, rustc}; + +fn main() { + rustc().input("foo.rs").crate_type("rlib").output("foo.xxx").run(); + create_symlink("foo.xxx", "libfoo.rlib"); + rustc().input("bar.rs").library_search_path(cwd()).run(); +} diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index 47bb1a059be5a..4773ac4ccf720 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied --> $DIR/typeck-default-trait-impl-precedence.rs:19:20 | LL | is_defaulted::<&'static u32>(); - | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted` + | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted` | note: required for `&'static u32` to implement `Defaulted` --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr index 6e41561f1a7b6..b6636d4de86eb 100644 --- a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr +++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot satisfy ` as Object>::Output == T` +error[E0284]: type annotations needed: cannot normalize ` as Object>::Output` --> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:41 | LL | foo::, U>(x) - | ^ cannot satisfy ` as Object>::Output == T` + | ^ cannot normalize ` as Object>::Output` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs index 0b66a6e783032..abfd51c2008bb 100644 --- a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs +++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs @@ -23,7 +23,7 @@ fn foo(x: >::Output) -> U { #[allow(dead_code)] fn transmute(x: T) -> U { foo::, U>(x) - //[next]~^ ERROR type annotations needed: cannot satisfy ` as Object>::Output == T` + //[next]~^ ERROR type annotations needed: cannot normalize ` as Object>::Output` } fn main() {} diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index f32bb1301da59..bd65cee58d9b4 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -16,11 +16,11 @@ LL | | for<'a> *const T: ToUnit<'a>, | = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details -error[E0284]: type annotations needed: cannot satisfy ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc == usize` +error[E0284]: type annotations needed: cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` --> $DIR/associated-type.rs:44:59 | LL | foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); - | ^^^^^^ cannot satisfy ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc == usize` + | ^^^^^^ cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` error: aborting due to 2 previous errors diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs index ac1236c554af2..df03d5f60a028 100644 --- a/tests/ui/coherence/occurs-check/associated-type.rs +++ b/tests/ui/coherence/occurs-check/associated-type.rs @@ -42,5 +42,5 @@ fn foo, U>(x: T::Assoc) -> T::Assoc { fn main() { foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); - //[next]~^ ERROR: cannot satisfy + //[next]~^ ERROR: cannot normalize } diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 568cb8931a198..d189d2dbdedc8 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -25,7 +25,7 @@ LL | SelectInt.check("bar"); = help: the trait `AsExpression` is implemented for `&str` = help: for that trait implementation, expected `Text`, found `Integer` -error[E0271]: type mismatch resolving `<&str as AsExpression<::SqlType>>::Expression == _` +error[E0271]: type mismatch resolving `::SqlType == Text` --> $DIR/as_expression.rs:57:5 | LL | SelectInt.check("bar"); diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr index 2c372b6c3a78e..9b5d84b5b090e 100644 --- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `i32: Baz` is not satisfied --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30 | LL | type Bar: Baz = i32; - | ^^^ the trait `Eq` is not implemented for `i32`, which is required by `i32: Baz` + | ^^^ the trait `Eq` is not implemented for `::Bar<()>`, which is required by `i32: Baz` | note: required for `i32` to implement `Baz` --> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23 diff --git a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr index 14a3d5e178d43..31d74d1c022a1 100644 --- a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr +++ b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: >::Assoc` +error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to >::Assoc` --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50 | LL | let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::(); - | ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: >::Assoc` + | ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to >::Assoc` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/associated-type-undefine.rs b/tests/ui/impl-trait/associated-type-undefine.rs new file mode 100644 index 0000000000000..c8f07021fbf16 --- /dev/null +++ b/tests/ui/impl-trait/associated-type-undefine.rs @@ -0,0 +1,28 @@ +#![feature(impl_trait_in_assoc_type)] + +trait Foo: Sized { + type Bar; + type Gat; + fn foo(self) -> (::Gat, ::Gat); +} + +impl Foo for u32 { + type Bar = (); + type Gat = (); + fn foo(self) -> (::Gat, ::Gat) { + ((), ()) + } +} + +impl Foo for () { + type Bar = impl Sized; + type Gat = ::Bar; + // Because we encounter `Gat` first, we never walk into another `Gat` + // again, thus missing the opaque type that we could be defining. + fn foo(self) -> (::Gat, ::Gat) { + ((), ()) + //~^ ERROR: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/associated-type-undefine.stderr b/tests/ui/impl-trait/associated-type-undefine.stderr new file mode 100644 index 0000000000000..5d9d525eb93bf --- /dev/null +++ b/tests/ui/impl-trait/associated-type-undefine.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/associated-type-undefine.rs:23:14 + | +LL | type Bar = impl Sized; + | ---------- the expected opaque type +... +LL | ((), ()) + | ^^ expected opaque type, found `()` + | + = note: expected opaque type `<() as Foo>::Bar` + found unit type `()` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/associated-type-undefine.rs:22:8 + | +LL | fn foo(self) -> (::Gat, ::Gat) { + | ^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index 1f9a2a5e9d600..a53312e5c0bd4 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -46,7 +46,7 @@ error[E0277]: the trait bound `impl Into: Into` is not satisfie --> $DIR/nested_impl_trait.rs:6:46 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Into`, which is required by `impl Into: Into` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug`, which is required by `impl Into: Into` | = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` @@ -55,7 +55,7 @@ error[E0277]: the trait bound `impl Into: Into` is not satisfie --> $DIR/nested_impl_trait.rs:19:34 | LL | fn bad(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Into`, which is required by `impl Into: Into` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug`, which is required by `impl Into: Into` | = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` diff --git a/tests/ui/kindck/kindck-send-object.stderr b/tests/ui/kindck/kindck-send-object.stderr index 9f1ff4f3644cc..7d0c711abc4c3 100644 --- a/tests/ui/kindck/kindck-send-object.stderr +++ b/tests/ui/kindck/kindck-send-object.stderr @@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa LL | assert_send::<&'static (dyn Dummy + 'static)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | - = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object.rs:5:18 diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr index f2aa814676fc3..7f39dab2086a1 100644 --- a/tests/ui/kindck/kindck-send-object1.stderr +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -4,7 +4,7 @@ error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely LL | assert_send::<&'a dyn Dummy>(); | ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely | - = help: the trait `Sync` is not implemented for `&'a (dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` = note: required for `&'a (dyn Dummy + 'a)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object1.rs:5:18 diff --git a/tests/ui/kindck/kindck-send-object2.stderr b/tests/ui/kindck/kindck-send-object2.stderr index cd4d74360f867..a481a132ccefb 100644 --- a/tests/ui/kindck/kindck-send-object2.stderr +++ b/tests/ui/kindck/kindck-send-object2.stderr @@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa LL | assert_send::<&'static dyn Dummy>(); | ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | - = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object2.rs:3:18 diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr index 3b6994b45d109..b132c56473eed 100644 --- a/tests/ui/suggestions/suggest-remove-refs-5.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr @@ -4,7 +4,7 @@ error[E0277]: `&mut &mut &mut &mut Vec` is not an iterator LL | for _ in &mut &mut v {} | ^^^^^^^^^^^ `&mut &mut &mut &mut Vec` is not an iterator | - = help: the trait `Iterator` is not implemented for `&mut &mut &mut &mut Vec`, which is required by `&mut &mut &mut &mut Vec: IntoIterator` + = help: the trait `Iterator` is not implemented for `Vec`, which is required by `&mut &mut &mut &mut Vec: IntoIterator` = note: required for `&mut Vec` to implement `Iterator` = note: 3 redundant requirements hidden = note: required for `&mut &mut &mut &mut Vec` to implement `Iterator` @@ -21,7 +21,7 @@ error[E0277]: `&mut &mut &mut [u8; 1]` is not an iterator LL | for _ in &mut v {} | ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator | - = help: the trait `Iterator` is not implemented for `&mut &mut &mut [u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` + = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` = note: required for `&mut [u8; 1]` to implement `Iterator` = note: 2 redundant requirements hidden = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator` diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs index 2607f047024dd..35757f2339dbf 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs @@ -18,3 +18,4 @@ fn weird1() -> impl !Sized + Sized {} //~^ ERROR type mismatch resolving `impl !Sized + Sized == ()` fn weird2() -> impl !Sized {} //~^ ERROR type mismatch resolving `impl !Sized == ()` +//~| ERROR the size for values of type `impl !Sized` cannot be known at compilation time diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr index ceaf42431fec2..3dd2b27b55b67 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr @@ -16,6 +16,15 @@ error[E0271]: type mismatch resolving `impl !Sized == ()` LL | fn weird2() -> impl !Sized {} | ^^^^^^^^^^^ types differ +error[E0277]: the size for values of type `impl !Sized` cannot be known at compilation time + --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 + | +LL | fn weird2() -> impl !Sized {} + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl !Sized` + = note: the return type of a function must have a statically known size + error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:12:13 | @@ -30,7 +39,7 @@ note: required by a bound in `consume` LL | fn consume(_: impl Trait) {} | ^^^^^ required by this bound in `consume` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0271, E0277. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr index 562d7ccf9fec0..e0b23bd8110a3 100644 --- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr +++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | is_send(foo()); | ^^^^^ future returned by `foo` is not `Send` | - = help: the trait `Sync` is not implemented for `impl Future`, which is required by `impl Future: Send` + = help: the trait `Sync` is not implemented for `NotSync`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/auto-with-drop_tracking_mir.rs:16:11 | diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr index 9dde1963bd49d..e0cbee88aa100 100644 --- a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr +++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot satisfy `{ || {} } == _` +error[E0284]: type annotations needed: cannot normalize `X::{constant#0}` --> $DIR/const-region-infer-to-static-in-binder.rs:4:10 | LL | struct X; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `{ || {} } == _` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}` error: using function pointers as const generic parameters is forbidden --> $DIR/const-region-infer-to-static-in-binder.rs:4:20 diff --git a/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr index 6bf4e3cb53493..9a18a58debd2f 100644 --- a/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr +++ b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `(): Foo` is not satisfied LL | needs_foo::<()>(); | ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo` | +help: this trait has no implementations, consider adding one + --> $DIR/point-at-failing-nested.rs:4:1 + | +LL | trait Bar {} + | ^^^^^^^^^ note: required for `()` to implement `Foo` --> $DIR/point-at-failing-nested.rs:9:12 | diff --git a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.rs b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.rs new file mode 100644 index 0000000000000..a3ab7bf03e55a --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Znext-solver + +trait Trait { + type Assoc; +} + +fn test_poly() { + let x: ::Assoc = (); + //~^ ERROR the trait bound `T: Trait` is not satisfied +} + +fn test() { + let x: ::Assoc = (); + //~^ ERROR the trait bound `i32: Trait` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr new file mode 100644 index 0000000000000..cd8d8b3ffcd38 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/projection-trait-ref.rs:8:12 + | +LL | let x: ::Assoc = (); + | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn test_poly() { + | +++++++ + +error[E0277]: the trait bound `i32: Trait` is not satisfied + --> $DIR/projection-trait-ref.rs:13:12 + | +LL | let x: ::Assoc = (); + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `i32` + | +help: this trait has no implementations, consider adding one + --> $DIR/projection-trait-ref.rs:3:1 + | +LL | trait Trait { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr index 77a0cc4975412..ab1d4a56c0234 100644 --- a/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr +++ b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr @@ -6,6 +6,11 @@ LL | needs_foo(()); | | | required by a bound introduced by this call | +help: this trait has no implementations, consider adding one + --> $DIR/where-clause-doesnt-apply.rs:2:1 + | +LL | trait Bar {} + | ^^^^^^^^^ note: required for `()` to implement `Foo` --> $DIR/where-clause-doesnt-apply.rs:4:9 | diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr index 3ef0afa38bff4..0c72fc25dca7a 100644 --- a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr @@ -2,13 +2,8 @@ error[E0271]: type mismatch resolving `::Assoc == i32` --> $DIR/param-candidate-shadows-project.rs:27:19 | LL | require_bar::(); - | ^ type mismatch resolving `::Assoc == i32` + | ^ types differ | -note: types differ - --> $DIR/param-candidate-shadows-project.rs:10:18 - | -LL | type Assoc = i32; - | ^^^ note: required for `T` to implement `Bar` --> $DIR/param-candidate-shadows-project.rs:13:9 | diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs index 12ea1bf142ab8..5239474ff44b2 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs @@ -24,7 +24,7 @@ fn needs_bar() {} fn foo + Foo>() { needs_bar::(); - //~^ ERROR type annotations needed: cannot satisfy `::Assoc == i32` + //~^ ERROR type annotations needed: cannot normalize } fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr index 21f3fbfeb872e..270ad85171779 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot satisfy `::Assoc == i32` +error[E0284]: type annotations needed: cannot normalize `::Assoc` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17 | LL | needs_bar::(); - | ^ cannot satisfy `::Assoc == i32` + | ^ cannot normalize `::Assoc` | note: required for `T` to implement `Bar` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9 diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index 524522bef098c..b96bfab927d2d 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -10,23 +10,23 @@ LL | #![feature(specialization)] error: cannot normalize `::Id: '_` -error[E0284]: type annotations needed: cannot satisfy `::Id == _` +error[E0284]: type annotations needed: cannot normalize `::Id` --> $DIR/specialization-transmute.rs:15:23 | LL | fn intu(&self) -> &Self::Id { - | ^^^^^^^^^ cannot satisfy `::Id == _` + | ^^^^^^^^^ cannot normalize `::Id` -error[E0284]: type annotations needed: cannot satisfy `T <: ::Id` +error[E0284]: type annotations needed: cannot satisfy `::Id normalizes-to T` --> $DIR/specialization-transmute.rs:17:9 | LL | self - | ^^^^ cannot satisfy `T <: ::Id` + | ^^^^ cannot satisfy `::Id normalizes-to T` -error[E0284]: type annotations needed: cannot satisfy `::Id == Option>` +error[E0284]: type annotations needed: cannot satisfy `::Id normalizes-to Option>` --> $DIR/specialization-transmute.rs:28:13 | LL | let s = transmute::>>(0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `::Id == Option>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `::Id normalizes-to Option>` | note: required by a bound in `transmute` --> $DIR/specialization-transmute.rs:21:25 diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.rs b/tests/ui/traits/next-solver/specialization-unconstrained.rs index e44246a1262ad..2bbe784011071 100644 --- a/tests/ui/traits/next-solver/specialization-unconstrained.rs +++ b/tests/ui/traits/next-solver/specialization-unconstrained.rs @@ -18,5 +18,5 @@ fn test, U>() {} fn main() { test::(); - //~^ ERROR cannot satisfy `::Id == ()` + //~^ ERROR cannot satisfy `::Id normalizes-to ()` } diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.stderr b/tests/ui/traits/next-solver/specialization-unconstrained.stderr index a6f6a4f260d41..e1d785b554bd3 100644 --- a/tests/ui/traits/next-solver/specialization-unconstrained.stderr +++ b/tests/ui/traits/next-solver/specialization-unconstrained.stderr @@ -8,11 +8,11 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -error[E0284]: type annotations needed: cannot satisfy `::Id == ()` +error[E0284]: type annotations needed: cannot satisfy `::Id normalizes-to ()` --> $DIR/specialization-unconstrained.rs:20:5 | LL | test::(); - | ^^^^^^^^^^^^^^^^^ cannot satisfy `::Id == ()` + | ^^^^^^^^^^^^^^^^^ cannot satisfy `::Id normalizes-to ()` | note: required by a bound in `test` --> $DIR/specialization-unconstrained.rs:17:20 diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr index 14b2ecbb9f2d7..bbfbb98fba774 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr +++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied --> $DIR/root-obligation.rs:6:38 | LL | .filter(|c| "aeiou".contains(c)) - | -------- ^ the trait `Fn(char)` is not implemented for `&char`, which is required by `&char: Pattern<'_>` + | -------- ^ the trait `Fn(char)` is not implemented for `char`, which is required by `&char: Pattern<'_>` | | | required by a bound introduced by this call | diff --git a/tests/ui/transmutability/enums/uninhabited_optimization.rs b/tests/ui/transmutability/enums/uninhabited_optimization.rs new file mode 100644 index 0000000000000..04a8eb40c8b8d --- /dev/null +++ b/tests/ui/transmutability/enums/uninhabited_optimization.rs @@ -0,0 +1,26 @@ +//@ check-pass +//! Tests that we do not regress rust-lang/rust#125811 +#![feature(transmutability)] + +fn assert_transmutable() +where + (): std::mem::BikeshedIntrinsicFrom +{} + +enum Uninhabited {} + +enum SingleInhabited { + X, + Y(Uninhabited) +} + +enum SingleUninhabited { + X(Uninhabited), + Y(Uninhabited), +} + +fn main() { + assert_transmutable::(); + assert_transmutable::(); + assert_transmutable::(); +} diff --git a/tests/ui/transmutability/references/unsafecell.stderr b/tests/ui/transmutability/references/unsafecell.stderr index 651eb8ceb2676..8bb323593554a 100644 --- a/tests/ui/transmutability/references/unsafecell.stderr +++ b/tests/ui/transmutability/references/unsafecell.stderr @@ -2,7 +2,7 @@ error[E0277]: `&u8` cannot be safely transmuted into `&UnsafeCell` --> $DIR/unsafecell.rs:27:50 | LL | assert::is_maybe_transmutable::<&'static u8, &'static UnsafeCell>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell` | note: required by a bound in `is_maybe_transmutable` --> $DIR/unsafecell.rs:12:14 @@ -17,7 +17,7 @@ error[E0277]: `&UnsafeCell` cannot be safely transmuted into `&UnsafeCell $DIR/unsafecell.rs:29:62 | LL | assert::is_maybe_transmutable::<&'static UnsafeCell, &'static UnsafeCell>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell` | note: required by a bound in `is_maybe_transmutable` --> $DIR/unsafecell.rs:12:14 diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr index 4c8a25edfedbe..5a728a00138c8 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr @@ -1,4 +1,4 @@ -error[E0284]: type annotations needed: cannot satisfy `>::Out == ()` +error[E0284]: type annotations needed: cannot satisfy `Bar == _` --> $DIR/issue-84660-unsoundness.rs:22:37 | LL | fn convert(_i: In) -> Self::Out { @@ -7,7 +7,7 @@ LL | | LL | | LL | | unreachable!(); LL | | } - | |_____^ cannot satisfy `>::Out == ()` + | |_____^ cannot satisfy `Bar == _` error[E0119]: conflicting implementations of trait `Trait` --> $DIR/issue-84660-unsoundness.rs:29:1 diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs index 73c8deb3a4d97..f3234bafd1153 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs @@ -20,7 +20,7 @@ trait Trait { impl Trait for Out { type Out = Out; fn convert(_i: In) -> Self::Out { - //[next]~^ ERROR: cannot satisfy `>::Out == ()` + //[next]~^ ERROR: cannot satisfy `Bar == _` //[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`, but has it in its signature unreachable!(); } diff --git a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.rs b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.rs new file mode 100644 index 0000000000000..d00b4f3313258 --- /dev/null +++ b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.rs @@ -0,0 +1,16 @@ +trait Foo<'s> {} + +impl<'s> Foo<'s> for () {} + +struct Bar; + +impl<'s, T: Foo<'s>> From for Bar { + fn from(_: T) -> Self { + Bar + } +} + +fn main() { + let _: Bar = ((),).into(); + //~^ ERROR he trait bound `((),): Into` is not satisfied +} diff --git a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr new file mode 100644 index 0000000000000..8410574e31129 --- /dev/null +++ b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `((),): Into` is not satisfied + --> $DIR/suggest-similar-impls-for-root-obligation.rs:14:24 + | +LL | let _: Bar = ((),).into(); + | ^^^^ the trait `Foo<'_>` is not implemented for `((),)`, which is required by `((),): Into<_>` + | + = help: the trait `Foo<'_>` is implemented for `()` + = help: for that trait implementation, expected `()`, found `((),)` +note: required for `Bar` to implement `From<((),)>` + --> $DIR/suggest-similar-impls-for-root-obligation.rs:7:22 + | +LL | impl<'s, T: Foo<'s>> From for Bar { + | ------- ^^^^^^^ ^^^ + | | + | unsatisfied trait bound introduced here + = note: required for `((),)` to implement `Into` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`.