diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b2d38a00f0b5f..ba6b9ef078467 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -11,6 +11,7 @@ #![allow(internal_features)] #![feature(decl_macro)] #![feature(let_chains)] +#![feature(panic_backtrace_config)] #![feature(panic_update_hook)] #![feature(result_flattening)] @@ -1317,8 +1318,8 @@ pub fn install_ice_hook( // by the user. Compiler developers and other rustc users can // opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE" // (e.g. `RUST_BACKTRACE=1`) - if std::env::var_os("RUST_BACKTRACE").is_none() { - std::env::set_var("RUST_BACKTRACE", "full"); + if env::var_os("RUST_BACKTRACE").is_none() { + panic::set_backtrace_style(panic::BacktraceStyle::Full); } let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default()); diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index c8caf228ffb5b..fb1db30c5f3d8 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -121,7 +121,18 @@ pub enum SelectionCandidate<'tcx> { /// Implementation of transmutability trait. TransmutabilityCandidate, - ParamCandidate(ty::PolyTraitPredicate<'tcx>), + /// A candidate from the `ParamEnv`. + ParamCandidate { + /// The actual `where`-bound, e.g. `T: Trait`. + predicate: ty::PolyTraitPredicate<'tcx>, + /// `true` if the where-bound has no bound vars and does + /// not refer to any parameters or inference variables. + /// + /// We prefer all other candidates over global where-bounds. + /// Notably, global where-bounds do not shadow impls. + is_global: bool, + }, + ImplCandidate(DefId), AutoImplCandidate, diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index 2ddcb8aab2530..9e94489902674 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -153,6 +153,8 @@ pub enum ProbeKind<'tcx> { /// do a probe to find out what projection type(s) may be used to prove that /// the source type upholds all of the target type's object bounds. UpcastProjectionCompatibility, + /// Looking for param-env candidates that satisfy the trait ref for a projection. + ShadowedEnvProbing, /// Try to unify an opaque type with an existing key in the storage. OpaqueTypeStorageLookup { result: QueryResult<'tcx> }, } diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index e652f0586c4ea..5b3c50cb97323 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -118,6 +118,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { ProbeKind::TraitCandidate { source, result } => { write!(self.f, "CANDIDATE {source:?}: {result:?}") } + ProbeKind::ShadowedEnvProbing => { + write!(self.f, "PROBING FOR IMPLS SHADOWED BY PARAM-ENV CANDIDATE:") + } }?; self.nested(|this| { diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 9a027d7f937ec..97bea28f06a3a 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -1,7 +1,7 @@ //! Code shared by trait and projection goals for candidate assembly. use crate::solve::GoalSource; -use crate::solve::{inspect, EvalCtxt, SolverMode}; +use crate::solve::{EvalCtxt, SolverMode}; use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; use rustc_middle::bug; @@ -16,7 +16,6 @@ use rustc_middle::ty::{fast_reject, TypeFoldable}; use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, DUMMY_SP}; use std::fmt::Debug; -use std::mem; pub(super) mod structural_traits; @@ -792,17 +791,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - // HACK: We temporarily remove the `ProofTreeBuilder` to - // avoid adding `Trait` candidates to the candidates used - // to prove the current goal. - let inspect = mem::replace(&mut self.inspect, inspect::ProofTreeBuilder::new_noop()); - let tcx = self.tcx(); let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> = goal.with(tcx, goal.predicate.trait_ref(tcx)); - let mut trait_candidates_from_env = Vec::new(); - self.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env); - self.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env); + + let mut trait_candidates_from_env = vec![]; + self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| { + ecx.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env); + ecx.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env); + }); + if !trait_candidates_from_env.is_empty() { let trait_env_result = self.merge_candidates(trait_candidates_from_env); match trait_env_result.unwrap().value.certainty { @@ -831,7 +829,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } } - self.inspect = inspect; } /// If there are multiple ways to prove a trait or projection goal, we have diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 6fda5f4af25e7..68c0c8bf09eac 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -176,7 +176,8 @@ fn to_selection<'tcx>( | ProbeKind::UnsizeAssembly | ProbeKind::UpcastProjectionCompatibility | ProbeKind::OpaqueTypeStorageLookup { result: _ } - | ProbeKind::Root { result: _ } => { + | ProbeKind::Root { result: _ } + | ProbeKind::ShadowedEnvProbing => { span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind()) } }) diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index fd36b7ffd4eb4..d7f6dc04a5534 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -290,12 +290,25 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { match *step { inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)), inspect::ProbeStep::NestedProbe(ref probe) => { - // Nested probes have to prove goals added in their parent - // but do not leak them, so we truncate the added goals - // afterwards. - let num_goals = nested_goals.len(); - self.candidates_recur(candidates, nested_goals, probe); - nested_goals.truncate(num_goals); + match probe.kind { + // These never assemble candidates for the goal we're trying to solve. + inspect::ProbeKind::UpcastProjectionCompatibility + | inspect::ProbeKind::ShadowedEnvProbing => continue, + + inspect::ProbeKind::NormalizedSelfTyAssembly + | inspect::ProbeKind::UnsizeAssembly + | inspect::ProbeKind::Root { .. } + | inspect::ProbeKind::TryNormalizeNonRigid { .. } + | inspect::ProbeKind::TraitCandidate { .. } + | inspect::ProbeKind::OpaqueTypeStorageLookup { .. } => { + // Nested probes have to prove goals added in their parent + // but do not leak them, so we truncate the added goals + // afterwards. + let num_goals = nested_goals.len(); + self.candidates_recur(candidates, nested_goals, probe); + nested_goals.truncate(num_goals); + } + } } inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { assert_eq!(shallow_certainty.replace(c), None); @@ -308,9 +321,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { } match probe.kind { - inspect::ProbeKind::NormalizedSelfTyAssembly - | inspect::ProbeKind::UnsizeAssembly - | inspect::ProbeKind::UpcastProjectionCompatibility => (), + inspect::ProbeKind::UpcastProjectionCompatibility + | inspect::ProbeKind::ShadowedEnvProbing => bug!(), + + inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly => {} // We add a candidate even for the root evaluation if there // is only one way to prove a given goal, e.g. for `WellFormed`. diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 2cc972cb98eb9..fe8c76ab94693 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -359,9 +359,12 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( ) -> IntersectionHasImpossibleObligations<'tcx> { let infcx = selcx.infcx; + // Elaborate obligations in case the current obligation is unknowable, + // but its super trait bound is not. See #124532 for more details. + let obligations = util::elaborate(infcx.tcx, obligations.iter().cloned()); if infcx.next_trait_solver() { let ocx = ObligationCtxt::new(infcx); - ocx.register_obligations(obligations.iter().cloned()); + ocx.register_obligations(obligations); let errors_and_ambiguities = ocx.select_all_or_error(); // We only care about the obligations that are *definitely* true errors. // Ambiguities do not prove the disjointness of two impls. @@ -388,7 +391,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( for obligation in obligations { // We use `evaluate_root_obligation` to correctly track intercrate // ambiguity clauses. - let evaluation_result = selcx.evaluate_root_obligation(obligation); + let evaluation_result = selcx.evaluate_root_obligation(&obligation); match evaluation_result { Ok(result) => { 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 a0260324da0a0..96793350c9ae4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -252,16 +252,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id()); // Keep only those bounds which may apply, and propagate overflow if it occurs. - for bound in matching_bounds { - if bound.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity { + for predicate in matching_bounds { + if predicate.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity + { continue; } // FIXME(oli-obk): it is suspicious that we are dropping the constness and // polarity here. - let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?; + let wc = self.where_clause_may_apply(stack, predicate.map_bound(|t| t.trait_ref))?; if wc.may_apply() { - candidates.vec.push(ParamCandidate(bound)); + let is_global = predicate.is_global() && !predicate.has_bound_vars(); + candidates.vec.push(ParamCandidate { predicate, is_global }); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 24c6951a014f6..e8b8ae0527541 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -57,9 +57,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Builtin(BuiltinImplSource::Misc, data) } - ParamCandidate(param) => { + ParamCandidate { predicate, is_global: _ } => { let obligations = - self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref)); + self.confirm_param_candidate(obligation, predicate.map_bound(|t| t.trait_ref)); ImplSource::Param(obligations) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3cf47e0f98e1f..124c7b6022bef 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1577,7 +1577,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return false; } match result { - Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(), + Ok(Some(SelectionCandidate::ParamCandidate { predicate, .. })) => { + !predicate.has_infer() + } _ => true, } } @@ -1829,23 +1831,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { return DropVictim::Yes; } - // Check if a bound would previously have been removed when normalizing - // 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(); - - // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, - // `DiscriminantKindCandidate`, `ConstDestructCandidate` - // to anything else. - // - // This is a fix for #53123 and prevents winnowing from accidentally extending the - // lifetime of a variable. match (&other.candidate, &victim.candidate) { - // FIXME(@jswrenn): this should probably be more sophisticated - (TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No, - - // (*) + // Prefer `BuiltinCandidate { has_nested: false }`, `ConstDestructCandidate` + // to anything else. + // + // This is a fix for #53123 and prevents winnowing from accidentally extending the + // lifetime of a variable. + ( + BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), + BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), + ) => bug!("two trivial builtin candidates: {other:?} {victim:?}"), (BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => { DropVictim::Yes } @@ -1853,7 +1848,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> { DropVictim::No } - (ParamCandidate(other), ParamCandidate(victim)) => { + // Global bounds from the where clause should be ignored + // here (see issue #50825). + (ParamCandidate { is_global: true, .. }, ParamCandidate { is_global: true, .. }) => { + DropVictim::No + } + (_, ParamCandidate { is_global: true, .. }) => DropVictim::Yes, + (ParamCandidate { is_global: true, .. }, _) => DropVictim::No, + + ( + ParamCandidate { is_global: false, predicate: other }, + ParamCandidate { is_global: false, predicate: victim }, + ) => { let same_except_bound_vars = other.skip_binder().trait_ref == victim.skip_binder().trait_ref && other.skip_binder().polarity == victim.skip_binder().polarity @@ -1870,68 +1876,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } } - // Drop otherwise equivalent non-const fn pointer candidates - (FnPointerCandidate { .. }, FnPointerCandidate { fn_host_effect }) => { - DropVictim::drop_if(*fn_host_effect == self.tcx().consts.true_) - } - - ( - ParamCandidate(ref other_cand), - ImplCandidate(..) - | AutoImplCandidate - | ClosureCandidate { .. } - | AsyncClosureCandidate - | AsyncFnKindHelperCandidate - | CoroutineCandidate - | FutureCandidate - | IteratorCandidate - | AsyncIteratorCandidate - | FnPointerCandidate { .. } - | BuiltinObjectCandidate - | BuiltinUnsizeCandidate - | TraitUpcastingUnsizeCandidate(_) - | BuiltinCandidate { .. } - | TraitAliasCandidate - | ObjectCandidate(_) - | ProjectionCandidate(_), - ) => { - // We have a where clause so don't go around looking - // for impls. Arbitrarily give param candidates priority - // over projection and object candidates. - // - // Global bounds from the where clause should be ignored - // here (see issue #50825). - DropVictim::drop_if(!is_global(other_cand)) - } - (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => { - // Prefer these to a global where-clause bound - // (see issue #50825). - if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No } - } - ( - ImplCandidate(_) - | AutoImplCandidate - | ClosureCandidate { .. } - | AsyncClosureCandidate - | AsyncFnKindHelperCandidate - | CoroutineCandidate - | FutureCandidate - | IteratorCandidate - | AsyncIteratorCandidate - | FnPointerCandidate { .. } - | BuiltinObjectCandidate - | BuiltinUnsizeCandidate - | TraitUpcastingUnsizeCandidate(_) - | BuiltinCandidate { has_nested: true } - | TraitAliasCandidate, - ParamCandidate(ref 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(), - ) - } + (ParamCandidate { is_global: false, .. }, _) => DropVictim::Yes, + (_, ParamCandidate { is_global: false, .. }) => DropVictim::No, (ProjectionCandidate(i), ProjectionCandidate(j)) | (ObjectCandidate(i), ObjectCandidate(j)) => { @@ -1944,44 +1890,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> { bug!("Have both object and projection candidate") } - // Arbitrarily give projection and object candidates priority. - ( - ObjectCandidate(_) | ProjectionCandidate(_), - ImplCandidate(..) - | AutoImplCandidate - | ClosureCandidate { .. } - | AsyncClosureCandidate - | AsyncFnKindHelperCandidate - | CoroutineCandidate - | FutureCandidate - | IteratorCandidate - | AsyncIteratorCandidate - | FnPointerCandidate { .. } - | BuiltinObjectCandidate - | BuiltinUnsizeCandidate - | TraitUpcastingUnsizeCandidate(_) - | BuiltinCandidate { .. } - | TraitAliasCandidate, - ) => DropVictim::Yes, + // Arbitrarily give projection candidates priority. + (ProjectionCandidate(_), _) => DropVictim::Yes, + (_, ProjectionCandidate(_)) => DropVictim::No, - ( - ImplCandidate(..) - | AutoImplCandidate - | ClosureCandidate { .. } - | AsyncClosureCandidate - | AsyncFnKindHelperCandidate - | CoroutineCandidate - | FutureCandidate - | IteratorCandidate - | AsyncIteratorCandidate - | FnPointerCandidate { .. } - | BuiltinObjectCandidate - | BuiltinUnsizeCandidate - | TraitUpcastingUnsizeCandidate(_) - | BuiltinCandidate { .. } - | TraitAliasCandidate, - ObjectCandidate(_) | ProjectionCandidate(_), - ) => DropVictim::No, + // Need to prioritize builtin trait object impls as + // `::type_id` should use the vtable method + // and not the method provided by the user-defined impl + // `impl Any for T { .. }`. + // + // cc #57893 + (ObjectCandidate(_), _) => DropVictim::Yes, + (_, ObjectCandidate(_)) => DropVictim::No, (&ImplCandidate(other_def), &ImplCandidate(victim_def)) => { // See if we can toss out `victim` based on specialization. @@ -2061,37 +1981,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } } - (AutoImplCandidate, ImplCandidate(_)) | (ImplCandidate(_), AutoImplCandidate) => { - DropVictim::No - } - - (AutoImplCandidate, _) | (_, AutoImplCandidate) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other global candidates: {:?} {:?}", - other, - victim - ); - } - - // Everything else is ambiguous + // Treat all non-trivial builtin impls and user-defined impls the same way. ( ImplCandidate(_) - | ClosureCandidate { .. } - | AsyncClosureCandidate - | AsyncFnKindHelperCandidate - | CoroutineCandidate - | FutureCandidate - | IteratorCandidate - | AsyncIteratorCandidate - | FnPointerCandidate { .. } - | BuiltinObjectCandidate - | BuiltinUnsizeCandidate - | TraitUpcastingUnsizeCandidate(_) + | AutoImplCandidate | BuiltinCandidate { has_nested: true } - | TraitAliasCandidate, - ImplCandidate(_) - | ClosureCandidate { .. } | AsyncClosureCandidate | AsyncFnKindHelperCandidate | CoroutineCandidate @@ -2099,11 +1993,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | IteratorCandidate | AsyncIteratorCandidate | FnPointerCandidate { .. } - | BuiltinObjectCandidate + | ClosureCandidate { .. } + | TraitAliasCandidate | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) - | BuiltinCandidate { has_nested: true } - | TraitAliasCandidate, + | TransmutabilityCandidate + | BuiltinObjectCandidate, + _, ) => DropVictim::No, } } diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md index b9a89c20cee40..9d593f8081025 100644 --- a/src/doc/style-guide/src/editions.md +++ b/src/doc/style-guide/src/editions.md @@ -43,6 +43,7 @@ include: - Miscellaneous `rustfmt` bugfixes. - Use version-sort (sort `x8`, `x16`, `x32`, `x64`, `x128` in that order). - Change "ASCIIbetical" sort to Unicode-aware "non-lowercase before lowercase". +- Format single associated type `where` clauses on the same line if they fit. ## Rust 2015/2018/2021 style edition diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index 0066a4bacb956..c0628691b7734 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -295,8 +295,18 @@ Prefer to use single-letter names for generic parameters. These rules apply for `where` clauses on any item. -If immediately following a closing bracket of any kind, write the keyword -`where` on the same line, with a space before it. +If a where clause is short, and appears on a short one-line function +declaration with no body or on a short type with no `=`, format it on +the same line as the declaration: + +```rust +fn new(&self) -> Self where Self: Sized; + +type Item<'a>: SomeTrait where Self: 'a; +``` + +Otherwise, if immediately following a closing bracket of any kind, write the +keyword `where` on the same line, with a space before it. Otherwise, put `where` on a new line at the same indentation level. Put each component of a `where` clause on its own line, block-indented. Use a trailing @@ -347,7 +357,7 @@ where ``` If a `where` clause is very short, prefer using an inline bound on the type -parameter. +parameter if possible. If a component of a `where` clause does not fit and contains `+`, break it before each `+` and block-indent the continuation lines. Put each bound on its @@ -421,9 +431,21 @@ Format associated types like type aliases. Where an associated type has a bound, put a space after the colon but not before: ```rust -pub type Foo: Bar; +type Foo: Bar; ``` +If an associated type is short, has no `=`, and has a `where` clause with only +one entry, format the entire type declaration including the `where` clause on +the same line if it fits: + +```rust +type Item<'a> where Self: 'a; +type Item<'a>: PartialEq + Send where Self: 'a; +``` + +If the associated type has a `=`, or if the `where` clause contains multiple +entries, format it across multiple lines as with a type alias. + ## extern items When writing extern items (such as `extern "C" fn`), always specify the ABI. diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index a931782e8ccbe..cda5613536242 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -4061,7 +4061,6 @@ ui/traits/issue-6128.rs ui/traits/issue-6334.rs ui/traits/issue-65284-suggest-generic-trait-bound.rs ui/traits/issue-65673.rs -ui/traits/issue-66768.rs ui/traits/issue-68295.rs ui/traits/issue-7013.rs ui/traits/issue-70944.rs diff --git a/tests/ui/associated-item/issue-105449.rs b/tests/ui/associated-item/issue-105449.rs index 5ccc317562bc6..c5562a3090835 100644 --- a/tests/ui/associated-item/issue-105449.rs +++ b/tests/ui/associated-item/issue-105449.rs @@ -1,13 +1,14 @@ -//@ check-pass //@ compile-flags: -C debug_assertions=yes -Zunstable-options -#[allow(dead_code)] +// This is a mutated variant of #66768 which has been removed +// as it no longer tests the original issue. fn problematic_function() where DefaultAlloc: FinAllok, { let e = Edge2dElement; let _ = Into::::into(e.map_reference_coords()); + //~^ ERROR the trait bound `Point: From<(Ure, R1, MStorage)>` is not satisfied } impl Allocator for DefaultAlloc { type Buffer = MStorage; diff --git a/tests/ui/associated-item/issue-105449.stderr b/tests/ui/associated-item/issue-105449.stderr new file mode 100644 index 0000000000000..cfb4c8bb66a36 --- /dev/null +++ b/tests/ui/associated-item/issue-105449.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `Point: From<(Ure, R1, MStorage)>` is not satisfied + --> $DIR/issue-105449.rs:10:33 + | +LL | let _ = Into::::into(e.map_reference_coords()); + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<(Ure, R1, MStorage)>` is not implemented for `Point`, which is required by `(Ure, R1, MStorage): Into` + | | + | required by a bound introduced by this call + | + = help: the trait `From<(Ure, Space, >::Buffer)>` is implemented for `Point` + = help: for that trait implementation, expected `Space`, found `R1` + = note: required for `(Ure, R1, MStorage)` to implement `Into` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr index 2ffb6000ec822..f0953e40602a4 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr @@ -11,8 +11,8 @@ LL | | for<'a> >::Assoc: WhereBound, LL | impl Trait for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` | - = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` = note: downstream crates may implement trait `WhereBound` for type ` as WithAssoc<'a>>::Assoc` + = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr index 49b236f9d2aa2..43f01b7e58813 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr @@ -11,8 +11,8 @@ LL | | for<'a> Box<>::Assoc>: WhereBound, LL | impl Trait for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` | - = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box< as WithAssoc<'a>>::Assoc>` + = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr index dcbb73bd1ff10..e273a4db1da77 100644 --- a/tests/ui/coherence/normalize-for-errors.current.stderr +++ b/tests/ui/coherence/normalize-for-errors.current.stderr @@ -8,6 +8,7 @@ LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Ite | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)` | = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs index 2288118676ab3..d212d85427ab8 100644 --- a/tests/ui/coherence/normalize-for-errors.rs +++ b/tests/ui/coherence/normalize-for-errors.rs @@ -18,5 +18,6 @@ impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} //~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, //~| NOTE conflicting implementation for `(Box<(MyType,)>, //~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions +//[current]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs new file mode 100644 index 0000000000000..0e56084d6548f --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs @@ -0,0 +1,18 @@ +// Added in #124532. While `(): Super` is knowable, `(): Sub` is not. +// +// We therefore elaborate super trait bounds in the implicit negative +// overlap check. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +trait Super {} +trait Sub: Super {} + +trait Overlap {} +impl> Overlap for U {} +impl Overlap for () {} + +fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs new file mode 100644 index 0000000000000..d1f2e8d1c1a15 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs @@ -0,0 +1,33 @@ +// A regression test for pyella-0.1.5 which broke when +// enabling the new solver in coherence. +// +// `Tensor: TensorValue` is knowable while `Tensor: TensorOp` +// may be implemented downstream. We previously didn't check the +// super trait bound in coherence, causing these impls to overlap. +// +// However, we did fail to normalize ` {} +pub trait TensorOp: TensorValue {} + +pub struct Tensor; +impl TensorCompare for Tensor {} +impl TensorCompare for T1 +where + T1: TensorOp, + T1::Unmasked: Sized, +{} + + +fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-nested.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-nested.current.stderr new file mode 100644 index 0000000000000..3cdf782286aea --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-nested.current.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` + --> $DIR/super-trait-knowable-nested.rs:19:1 + | +LL | impl> Overlap for U {} + | ------------------------------------- first implementation here +LL | impl Overlap for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: downstream crates may implement trait `Bound<_>` for type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-nested.next.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-nested.next.stderr new file mode 100644 index 0000000000000..3cdf782286aea --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-nested.next.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` + --> $DIR/super-trait-knowable-nested.rs:19:1 + | +LL | impl> Overlap for U {} + | ------------------------------------- first implementation here +LL | impl Overlap for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: downstream crates may implement trait `Bound<_>` for type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-nested.rs b/tests/ui/coherence/super-traits/super-trait-knowable-nested.rs new file mode 100644 index 0000000000000..73e7c9a12bea4 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-nested.rs @@ -0,0 +1,22 @@ +// Unlike in `super-trait-knowable-1.rs`, the knowable +// super trait bound is in a nested goal and we currently +// only elaborate in the root. This can, and should, be# +// changed in the future. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +trait Super {} +trait Sub: Super {} + +trait Bound {} + +impl, U> Bound for T {} + +trait Overlap {} +impl> Overlap for U {} +impl Overlap for () {} +//~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()` + +fn main() {} diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs index cbdc10bd2e1ea..48e688cbd36fd 100644 --- a/tests/ui/issues/issue-48728.rs +++ b/tests/ui/issues/issue-48728.rs @@ -1,7 +1,12 @@ // Regression test for #48728, an ICE that occurred computing // coherence "help" information. -#[derive(Clone)] //~ ERROR conflicting implementations of trait `Clone` +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +#[derive(Clone)] struct Node(Box); impl Clone for Node<[T]> { diff --git a/tests/ui/lifetimes/issue-34979.rs b/tests/ui/lifetimes/issue-34979.rs index 252486dd92192..08b2f9ffcc477 100644 --- a/tests/ui/lifetimes/issue-34979.rs +++ b/tests/ui/lifetimes/issue-34979.rs @@ -3,7 +3,7 @@ impl<'a, T> Foo for &'a T {} struct Ctx<'a>(&'a ()) where - &'a (): Foo, //~ ERROR: type annotations needed - &'static (): Foo; + &'a (): Foo, + &'static (): Foo; //~ ERROR: mismatched types fn main() {} diff --git a/tests/ui/lifetimes/issue-34979.stderr b/tests/ui/lifetimes/issue-34979.stderr index 0877f1548a842..99aac7ac3b994 100644 --- a/tests/ui/lifetimes/issue-34979.stderr +++ b/tests/ui/lifetimes/issue-34979.stderr @@ -1,20 +1,18 @@ -error[E0283]: type annotations needed: cannot satisfy `&'a (): Foo` - --> $DIR/issue-34979.rs:6:13 +error[E0308]: mismatched types + --> $DIR/issue-34979.rs:7:18 | -LL | &'a (): Foo, - | ^^^ +LL | &'static (): Foo; + | ^^^ lifetime mismatch | -note: multiple `impl`s or `where` clauses satisfying `&'a (): Foo` found - --> $DIR/issue-34979.rs:2:1 + = note: expected trait `<&'static () as Foo>` + found trait `<&'a () as Foo>` +note: the lifetime `'a` as defined here... + --> $DIR/issue-34979.rs:4:12 | -LL | impl<'a, T> Foo for &'a T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | &'a (): Foo, - | ^^^ -LL | &'static (): Foo; - | ^^^ +LL | struct Ctx<'a>(&'a ()) + | ^^ + = note: ...does not necessarily outlive the static lifetime error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/issue-66768.rs b/tests/ui/traits/issue-66768.rs deleted file mode 100644 index dc9fe361019a2..0000000000000 --- a/tests/ui/traits/issue-66768.rs +++ /dev/null @@ -1,205 +0,0 @@ -// Regression test for #66768. -//@ check-pass -#![allow(dead_code)] -//-^ "dead code" is needed to reproduce the issue. - -use std::marker::PhantomData; -use std::ops::{Add, Mul}; - -fn problematic_function(material_surface_element: Edge2dElement) -where - DefaultAllocator: FiniteElementAllocator, -{ - let _: Point2 = material_surface_element.map_reference_coords().into(); -} - -impl ArrayLength for UTerm { - type ArrayType = (); -} -impl> ArrayLength for UInt { - type ArrayType = GenericArrayImplEven; -} -impl> ArrayLength for UInt { - type ArrayType = GenericArrayImplOdd; -} -impl Add for UTerm { - type Output = U; - fn add(self, _: U) -> Self::Output { - unimplemented!() - } -} -impl Add> for UInt -where - Ul: Add, -{ - type Output = UInt, B1>; - fn add(self, _: UInt) -> Self::Output { - unimplemented!() - } -} -impl Mul for UTerm { - type Output = UTerm; - fn mul(self, _: U) -> Self { - unimplemented!() - } -} -impl Mul> for UInt -where - Ul: Mul>, -{ - type Output = UInt>, B0>; - fn mul(self, _: UInt) -> Self::Output { - unimplemented!() - } -} -impl Mul> for UInt -where - Ul: Mul>, - UInt>, B0>: Add>, -{ - type Output = Sum>, B0>, UInt>; - fn mul(self, _: UInt) -> Self::Output { - unimplemented!() - } -} -impl Allocator for DefaultAllocator -where - R: DimName, - C: DimName, - R::Value: Mul, - Prod: ArrayLength, -{ - type Buffer = ArrayStorage; - fn allocate_uninitialized(_: R, _: C) -> Self::Buffer { - unimplemented!() - } - fn allocate_from_iterator(_: R, _: C, _: I) -> Self::Buffer { - unimplemented!() - } -} -impl Allocator for DefaultAllocator { - type Buffer = VecStorage; - fn allocate_uninitialized(_: Dynamic, _: C) -> Self::Buffer { - unimplemented!() - } - fn allocate_from_iterator(_: Dynamic, _: C, _: I) -> Self::Buffer { - unimplemented!() - } -} -impl DimName for DimU1 { - type Value = U1; - fn name() -> Self { - unimplemented!() - } -} -impl DimName for DimU2 { - type Value = U2; - fn name() -> Self { - unimplemented!() - } -} -impl From> for Point -where - DefaultAllocator: Allocator, -{ - fn from(_: VectorN) -> Self { - unimplemented!() - } -} -impl FiniteElementAllocator for DefaultAllocator where - DefaultAllocator: Allocator + Allocator -{ -} -impl ReferenceFiniteElement for Edge2dElement { - type NodalDim = DimU1; -} -impl FiniteElement for Edge2dElement { - fn map_reference_coords(&self) -> Vector2 { - unimplemented!() - } -} - -type Owned = >::Buffer; -type MatrixMN = Matrix>; -type VectorN = MatrixMN; -type Vector2 = VectorN; -type Point2 = Point; -type U1 = UInt; -type U2 = UInt, B0>; -type Sum = >::Output; -type Prod = >::Output; - -struct GenericArray> { - _data: U::ArrayType, -} -struct GenericArrayImplEven { - _parent2: U, - _marker: T, -} -struct GenericArrayImplOdd { - _parent2: U, - _data: T, -} -struct B0; -struct B1; -struct UTerm; -struct UInt { - _marker: PhantomData<(U, B)>, -} -struct DefaultAllocator; -struct Dynamic; -struct DimU1; -struct DimU2; -struct Matrix { - _data: S, - _phantoms: PhantomData<(N, R, C)>, -} -struct ArrayStorage -where - R: DimName, - C: DimName, - R::Value: Mul, - Prod: ArrayLength, -{ - _data: GenericArray>, -} -struct VecStorage { - _data: N, - _nrows: R, - _ncols: C, -} -struct Point -where - DefaultAllocator: Allocator, -{ - _coords: VectorN, -} -struct Edge2dElement; - -trait ArrayLength { - type ArrayType; -} -trait Allocator { - type Buffer; - fn allocate_uninitialized(nrows: R, ncols: C) -> Self::Buffer; - fn allocate_from_iterator(nrows: R, ncols: C, iter: I) -> Self::Buffer; -} -trait DimName { - type Value; - fn name() -> Self; -} -trait FiniteElementAllocator: - Allocator + Allocator -{ -} -trait ReferenceFiniteElement { - type NodalDim; -} -trait FiniteElement: ReferenceFiniteElement -where - DefaultAllocator: FiniteElementAllocator, -{ - fn map_reference_coords(&self) -> VectorN; -} - -fn main() {} diff --git a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr index 6e68646fbe4f4..3f0369bac5882 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr @@ -1,11 +1,12 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `W>>>>>>>>>>>>>>>>>>>>>` +error[E0119]: conflicting implementations of trait `Trait` for type `W>>>>>>>>>>>>>>>>>>>>>>` --> $DIR/coherence-fulfill-overflow.rs:12:1 | LL | impl Trait for W {} | ------------------------------------- first implementation here LL | impl Trait for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W>>>>>>>>>>>>>>>>>>>>>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W>>>>>>>>>>>>>>>>>>>>>>` | + = note: overflow evaluating the requirement `W>>>>: TwoW` = note: overflow evaluating the requirement `W>>>: TwoW` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`coherence_fulfill_overflow`) diff --git a/tests/ui/traits/normalize-conflicting-impls.rs b/tests/ui/traits/normalize-conflicting-impls.rs index 454b2fd015357..24185e213b6d4 100644 --- a/tests/ui/traits/normalize-conflicting-impls.rs +++ b/tests/ui/traits/normalize-conflicting-impls.rs @@ -1,8 +1,11 @@ +// This is a mutated variant of #66768 which has been removed +// as it no longer tests the original issue. fn problematic_function(material_surface_element: ()) where DefaultAllocator: FiniteElementAllocator<(), Space>, { let _: Point2 = material_surface_element.map_reference_coords().into(); + //~^ ERROR the trait bound `Point: From>` is not satisfied } impl Allocator for DefaultAllocator diff --git a/tests/ui/traits/normalize-conflicting-impls.stderr b/tests/ui/traits/normalize-conflicting-impls.stderr index 9a66fe00c3fe4..d3fa5162128fd 100644 --- a/tests/ui/traits/normalize-conflicting-impls.stderr +++ b/tests/ui/traits/normalize-conflicting-impls.stderr @@ -1,11 +1,11 @@ error[E0220]: associated type `Value` not found for `R` - --> $DIR/normalize-conflicting-impls.rs:10:8 + --> $DIR/normalize-conflicting-impls.rs:13:8 | LL | R::Value: DimName, | ^^^^^ associated type `Value` not found error[E0119]: conflicting implementations of trait `Allocator<_, ()>` for type `DefaultAllocator` - --> $DIR/normalize-conflicting-impls.rs:14:1 + --> $DIR/normalize-conflicting-impls.rs:17:1 | LL | / impl Allocator for DefaultAllocator LL | | where @@ -15,7 +15,17 @@ LL | | R::Value: DimName, LL | impl Allocator for DefaultAllocator {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `DefaultAllocator` -error: aborting due to 2 previous errors +error[E0277]: the trait bound `Point: From>` is not satisfied + --> $DIR/normalize-conflicting-impls.rs:7:74 + | +LL | let _: Point2 = material_surface_element.map_reference_coords().into(); + | ^^^^ the trait `From>` is not implemented for `Point`, which is required by `Matrix<()>: Into<_>` + | + = help: the trait `From>::Buffer>>` is implemented for `Point` + = help: for that trait implementation, expected `>::Buffer`, found `()` + = note: required for `Matrix<()>` to implement `Into>` + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0119, E0220. +Some errors have detailed explanations: E0119, E0220, E0277. For more information about an error, try `rustc --explain E0119`. diff --git a/triagebot.toml b/triagebot.toml index 3d22da56f7c75..ddab670178646 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -419,7 +419,7 @@ message_on_add = """\ - Priority? - Regression? - Notify people/groups? -- Needs `I-nominated`? +- Needs `I-{team}-nominated`? """ message_on_remove = "Issue #{number}'s prioritization request has been removed." message_on_close = "Issue #{number} has been closed while requested for prioritization."