diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index c498e6b3c83da..32a74b335c117 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -6,6 +6,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TypeVisitable}; use rustc_query_system::cache::Cache; +use rustc_type_ir::solve::AliasBoundKind; use self::EvaluationResult::*; use super::{SelectionError, SelectionResult}; @@ -116,8 +117,13 @@ pub enum SelectionCandidate<'tcx> { /// This is a trait matching with a projected type as `Self`, and we found /// an applicable bound in the trait definition. The `usize` is an index - /// into the list returned by `tcx.item_bounds`. - ProjectionCandidate(usize), + /// into the list returned by `tcx.item_bounds` and the `AliasBoundKind` + /// is whether this is candidate from recursion on the self type of a + /// projection. + ProjectionCandidate { + idx: usize, + kind: AliasBoundKind, + }, /// Implementation of a `Fn`-family trait by one of the anonymous types /// generated for an `||` expression. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3c5c21a7a89c2..de2b2e6c64f25 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -521,6 +521,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.is_default_trait(def_id) } + fn is_sizedness_trait(self, def_id: DefId) -> bool { + self.is_sizedness_trait(def_id) + } + fn as_lang_item(self, def_id: DefId) -> Option { lang_item_to_solver_lang_item(self.lang_items().from_def_id(def_id)?) } @@ -1787,6 +1791,10 @@ impl<'tcx> TyCtxt<'tcx> { .any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id)) } + pub fn is_sizedness_trait(self, def_id: DefId) -> bool { + matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized)) + } + /// Returns a range of the start/end indices specified with the /// `rustc_layout_scalar_valid_range` attribute. // FIXME(eddyb) this is an awkward spot for this method, maybe move it? diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ce4de6b95e0bb..b6adc606b8736 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -59,7 +59,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt; )] use rustc_type_ir::inherent; pub use rustc_type_ir::relate::VarianceDiagInfo; -pub use rustc_type_ir::solve::SizedTraitKind; +pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind}; pub use rustc_type_ir::*; #[allow(hidden_glob_reexports, unused_imports)] use rustc_type_ir::{InferCtxtLike, Interner}; diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index d58c264841c85..c9a42dddac42b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -9,7 +9,7 @@ use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; use rustc_type_ir::search_graph::CandidateHeadUsages; -use rustc_type_ir::solve::SizedTraitKind; +use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind}; use rustc_type_ir::{ self as ty, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, @@ -27,11 +27,6 @@ use crate::solve::{ has_no_inference_or_external_constraints, }; -enum AliasBoundKind { - SelfBounds, - NonSelfBounds, -} - /// A candidate is a possible way to prove a goal. /// /// It consists of both the `source`, which describes how that goal would be proven, @@ -451,7 +446,7 @@ where matches!( c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal) - | CandidateSource::AliasBound + | CandidateSource::AliasBound(_) ) && has_no_inference_or_external_constraints(c.result) }) { @@ -711,7 +706,7 @@ where self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) { candidates.push(Candidate { - source: CandidateSource::AliasBound, + source: CandidateSource::AliasBound(consider_self_bounds), result, head_usages: CandidateHeadUsages::default(), }); @@ -735,7 +730,7 @@ where { candidates.extend(G::probe_and_consider_implied_clause( self, - CandidateSource::AliasBound, + CandidateSource::AliasBound(consider_self_bounds), goal, assumption, [], @@ -750,7 +745,7 @@ where { candidates.extend(G::probe_and_consider_implied_clause( self, - CandidateSource::AliasBound, + CandidateSource::AliasBound(consider_self_bounds), goal, assumption, [], @@ -1030,7 +1025,7 @@ where item_bound.fold_with(&mut ReplaceOpaque { cx: self.cx(), alias_ty, self_ty }); candidates.extend(G::probe_and_match_goal_against_assumption( self, - CandidateSource::AliasBound, + CandidateSource::AliasBound(AliasBoundKind::SelfBounds), goal, assumption, |ecx| { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 65a5edf6b7250..48bd0963c8743 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -4,8 +4,8 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; -use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::solve::inspect::ProbeKind; +use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind}; use rustc_type_ir::{self as ty, Interner, TypingMode, elaborate}; use tracing::instrument; @@ -96,7 +96,7 @@ where ) { candidates.extend(Self::probe_and_match_goal_against_assumption( ecx, - CandidateSource::AliasBound, + CandidateSource::AliasBound(AliasBoundKind::SelfBounds), goal, clause, |ecx| { diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index e790ecd595be7..168921655a394 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -4,7 +4,9 @@ use rustc_type_ir::data_structures::IndexSet; use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; -use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind}; +use rustc_type_ir::solve::{ + AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, SizedTraitKind, +}; use rustc_type_ir::{ self as ty, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode, Upcast as _, elaborate, @@ -1355,6 +1357,7 @@ where #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_trait_candidates( &mut self, + candidate_preference_mode: CandidatePreferenceMode, mut candidates: Vec>, failed_candidate_info: FailedCandidateInfo, ) -> Result<(CanonicalResponse, Option), NoSolution> { @@ -1380,6 +1383,23 @@ where return Ok((candidate.result, Some(TraitGoalProvenVia::Misc))); } + // Extract non-nested alias bound candidates, will be preferred over where bounds if + // we're proving an auto-trait, sizedness trait or default trait. + if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker) + && candidates.iter().any(|c| { + matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds)) + }) + { + let alias_bounds: Vec<_> = candidates + .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..))) + .collect(); + return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) { + Ok((response, Some(TraitGoalProvenVia::AliasBound))) + } else { + Ok((self.bail_with_ambiguity(&alias_bounds), None)) + }; + } + // If there are non-global where-bounds, prefer where-bounds // (including global ones) over everything else. let has_non_global_where_bounds = candidates @@ -1427,9 +1447,10 @@ where }; } - if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)) { + // Next, prefer any alias bound (nested or otherwise). + if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) { let alias_bounds: Vec<_> = candidates - .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound)) + .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_))) .collect(); return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) { Ok((response, Some(TraitGoalProvenVia::AliasBound))) @@ -1470,7 +1491,9 @@ where ) -> Result<(CanonicalResponse, Option), NoSolution> { let (candidates, failed_candidate_info) = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All); - self.merge_trait_candidates(candidates, failed_candidate_info) + let candidate_preference_mode = + CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id()); + self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info) } fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option, NoSolution>> { diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index 8d01c880f8c59..d7e7ffd5d28c6 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -126,7 +126,9 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>( // Prefer dyn candidates over non-dyn candidates. This is necessary to // handle the unsoundness between `impl Any for T` and `dyn Any: Any`. ( - CandidateSource::Impl(_) | CandidateSource::ParamEnv(_) | CandidateSource::AliasBound, + CandidateSource::Impl(_) + | CandidateSource::ParamEnv(_) + | CandidateSource::AliasBound(_), CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }), ) => true, @@ -175,7 +177,9 @@ fn to_selection<'tcx>( }) } CandidateSource::BuiltinImpl(builtin) => ImplSource::Builtin(builtin, nested), - CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => ImplSource::Param(nested), + CandidateSource::ParamEnv(_) | CandidateSource::AliasBound(_) => { + ImplSource::Param(nested) + } CandidateSource::CoherenceUnknowable => { span_bug!(span, "didn't expect to select an unknowable candidate") } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 042d6def84c33..fab5102427c70 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -741,7 +741,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( let mut ambiguous = false; let _ = selcx.for_each_item_bound( obligation.predicate.self_ty(), - |selcx, clause, _| { + |selcx, clause, _, _| { let Some(clause) = clause.as_projection_clause() else { return ControlFlow::Continue(()); }; 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 60f1fcb26c004..cb980d5ce8b43 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -208,7 +208,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut distinct_normalized_bounds = FxHashSet::default(); let _ = self.for_each_item_bound::( placeholder_trait_predicate.self_ty(), - |selcx, bound, idx| { + |selcx, bound, idx, alias_bound_kind| { let Some(bound) = bound.as_trait_clause() else { return ControlFlow::Continue(()); }; @@ -230,12 +230,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bound.map_bound(|pred| pred.trait_ref), ) { Ok(None) => { - candidates.vec.push(ProjectionCandidate(idx)); + candidates + .vec + .push(ProjectionCandidate { idx, kind: alias_bound_kind }); } Ok(Some(normalized_trait)) if distinct_normalized_bounds.insert(normalized_trait) => { - candidates.vec.push(ProjectionCandidate(idx)); + candidates + .vec + .push(ProjectionCandidate { idx, kind: alias_bound_kind }); } _ => {} } @@ -825,7 +829,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::Alias(ty::Opaque, alias) => { - if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) { + if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate { .. })) { // We do not generate an auto impl candidate for `impl Trait`s which already // reference our auto trait. // diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 708a53f6c650d..66311de7446b0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Builtin(BuiltinImplSource::Misc, data) } - ProjectionCandidate(idx) => { + ProjectionCandidate { idx, .. } => { let obligations = self.confirm_projection_candidate(obligation, idx)?; ImplSource::Param(obligations) } @@ -144,15 +144,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, idx: usize, ) -> Result, SelectionError<'tcx>> { - let tcx = self.tcx(); - let placeholder_trait_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref; let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty()); let candidate_predicate = self .for_each_item_bound( placeholder_self_ty, - |_, clause, clause_idx| { + |_, clause, clause_idx, _| { if clause_idx == idx { ControlFlow::Break(clause) } else { @@ -194,28 +192,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|_| SelectionError::Unimplemented)?, ); - // FIXME(compiler-errors): I don't think this is needed. - if let ty::Alias(ty::Projection, alias_ty) = placeholder_self_ty.kind() { - let predicates = tcx.predicates_of(alias_ty.def_id).instantiate_own(tcx, alias_ty.args); - for (predicate, _) in predicates { - let normalized = normalize_with_depth_to( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - predicate, - &mut obligations, - ); - obligations.push(Obligation::with_depth( - self.tcx(), - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - normalized, - )); - } - } - Ok(obligations) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fb4f28412d428..9be5d0673f73c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -28,9 +28,11 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::{ - self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt, - TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate, may_use_unstable_feature, + self, CandidatePreferenceMode, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, + SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate, + may_use_unstable_feature, }; +use rustc_next_trait_solver::solve::AliasBoundKind; use rustc_span::{Symbol, sym}; use tracing::{debug, instrument, trace}; @@ -474,7 +476,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } else { let has_non_region_infer = stack.obligation.predicate.has_non_region_infer(); - if let Some(candidate) = self.winnow_candidates(has_non_region_infer, candidates) { + let candidate_preference_mode = + CandidatePreferenceMode::compute(self.tcx(), stack.obligation.predicate.def_id()); + if let Some(candidate) = + self.winnow_candidates(has_non_region_infer, candidate_preference_mode, candidates) + { self.filter_reservation_impls(candidate) } else { Ok(None) @@ -1623,11 +1629,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub(super) fn for_each_item_bound( &mut self, mut self_ty: Ty<'tcx>, - mut for_each: impl FnMut(&mut Self, ty::Clause<'tcx>, usize) -> ControlFlow, + mut for_each: impl FnMut( + &mut Self, + ty::Clause<'tcx>, + usize, + AliasBoundKind, + ) -> ControlFlow, on_ambiguity: impl FnOnce(), ) -> ControlFlow { let mut idx = 0; - let mut in_parent_alias_type = false; + let mut alias_bound_kind = AliasBoundKind::SelfBounds; loop { let (kind, alias_ty) = match *self_ty.kind() { @@ -1643,14 +1654,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // share the same type as `self_ty`. This is because for truly rigid // projections, we will never be able to equate, e.g. `::A` // with `<::A as Tr>::A`. - let relevant_bounds = if in_parent_alias_type { + let relevant_bounds = if matches!(alias_bound_kind, AliasBoundKind::NonSelfBounds) { self.tcx().item_non_self_bounds(alias_ty.def_id) } else { self.tcx().item_self_bounds(alias_ty.def_id) }; for bound in relevant_bounds.instantiate(self.tcx(), alias_ty.args) { - for_each(self, bound, idx)?; + for_each(self, bound, idx, alias_bound_kind)?; idx += 1; } @@ -1660,7 +1671,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return ControlFlow::Continue(()); } - in_parent_alias_type = true; + alias_bound_kind = AliasBoundKind::NonSelfBounds; } } @@ -1821,6 +1832,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn winnow_candidates( &mut self, has_non_region_infer: bool, + candidate_preference_mode: CandidatePreferenceMode, mut candidates: Vec>, ) -> Option> { if candidates.len() == 1 { @@ -1874,6 +1886,29 @@ impl<'tcx> SelectionContext<'_, 'tcx> { break; } + let mut alias_bounds = candidates.iter().filter_map(|c| { + if let ProjectionCandidate { idx, kind } = c.candidate { + Some((idx, kind)) + } else { + None + } + }); + // Extract non-nested alias bound candidates, will be preferred over where bounds if + // we're proving an auto-trait, sizedness trait or default trait. + if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker) { + match alias_bounds + .clone() + .filter_map(|(idx, kind)| (kind == AliasBoundKind::SelfBounds).then_some(idx)) + .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) }) + { + Some(Some(idx)) => { + return Some(ProjectionCandidate { idx, kind: AliasBoundKind::SelfBounds }); + } + Some(None) => {} + None => return None, + } + } + // The next highest priority is for non-global where-bounds. However, while we don't // prefer global where-clauses here, we do bail with ambiguity when encountering both // a global and a non-global where-clause. @@ -1907,12 +1942,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // fairly arbitrary but once again necessary for backwards compatibility. // If there are multiple applicable candidates which don't affect type inference, // choose the one with the lowest index. - let alias_bound = candidates - .iter() - .filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None }) - .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) }); - match alias_bound { - Some(Some(index)) => return Some(ProjectionCandidate(index)), + match alias_bounds.try_reduce(|(c1, k1), (c2, k2)| { + if has_non_region_infer { + None + } else if c1 < c2 { + Some((c1, k1)) + } else { + Some((c2, k2)) + } + }) { + Some(Some((idx, kind))) => return Some(ProjectionCandidate { idx, kind }), Some(None) => {} None => return None, } @@ -2001,7 +2040,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Non-global param candidates have already been handled, global // where-bounds get ignored. ParamCandidate(_) | ImplCandidate(_) => true, - ProjectionCandidate(_) | ObjectCandidate(_) => unreachable!(), + ProjectionCandidate { .. } | ObjectCandidate(_) => unreachable!(), }) { return Some(ImplCandidate(def_id)); } else { diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 335942d5bcc54..e1d1ad1b3765f 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -383,13 +383,6 @@ pub fn sizedness_fast_path<'tcx>( _ => return false, }; - // FIXME(sized_hierarchy): this temporarily reverts the `sized_hierarchy` feature - // while a proper fix for `tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs` - // is pending a proper fix - if !tcx.features().sized_hierarchy() && matches!(sizedness, SizedTraitKind::MetaSized) { - return true; - } - if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) { debug!("fast path -- trivial sizedness"); return true; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 4b6349e2f4269..023dbd38d9112 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -333,6 +333,8 @@ pub trait Interner: fn is_default_trait(self, def_id: Self::TraitId) -> bool; + fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool; + fn as_lang_item(self, def_id: Self::DefId) -> Option; fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option; diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 9d9a8e4984786..1e0263b232f4b 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -109,6 +109,30 @@ pub struct QueryInput { impl Eq for QueryInput {} +/// Which trait candidates should be preferred over other candidates? By default, prefer where +/// bounds over alias bounds. For marker traits, prefer alias bounds over where bounds. +#[derive(Clone, Copy, Debug)] +pub enum CandidatePreferenceMode { + /// Prefers where bounds over alias bounds + Default, + /// Prefers alias bounds over where bounds + Marker, +} + +impl CandidatePreferenceMode { + /// Given `trait_def_id`, which candidate preference mode should be used? + pub fn compute(cx: I, trait_id: I::TraitId) -> CandidatePreferenceMode { + let is_sizedness_or_auto_or_default_goal = cx.is_sizedness_trait(trait_id) + || cx.trait_is_auto(trait_id) + || cx.is_default_trait(trait_id); + if is_sizedness_or_auto_or_default_goal { + CandidatePreferenceMode::Marker + } else { + CandidatePreferenceMode::Default + } + } +} + /// Possible ways the given goal can be proven. #[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)] pub enum CandidateSource { @@ -165,7 +189,7 @@ pub enum CandidateSource { /// let _y = x.clone(); /// } /// ``` - AliasBound, + AliasBound(AliasBoundKind), /// A candidate that is registered only during coherence to represent some /// yet-unknown impl that could be produced downstream without violating orphan /// rules. @@ -183,6 +207,15 @@ pub enum ParamEnvSource { Global, } +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +pub enum AliasBoundKind { + /// Alias bound from the self type of a projection + SelfBounds, + // Alias bound having recursed on the self type of a projection + NonSelfBounds, +} + #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] #[cfg_attr( feature = "nightly", diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 4b767d8d62218..5fd0611a18434 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1057,7 +1057,7 @@ marker_impls! { #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub const trait Destruct {} +pub const trait Destruct: PointeeSized {} /// A marker for tuple types. /// diff --git a/tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr deleted file mode 100644 index b47db2b19ffe2..0000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error: implementation of `FnOnce` is not general enough - --> $DIR/higher-ranked-auto-trait-14.rs:20:5 - | -LL | / async move { -LL | | let xs = unique_x.union(&cached) -LL | | // .copied() // works -LL | | .map(|x| *x) // error -LL | | ; -LL | | let blah = val.blah(xs.into_iter()).await; -LL | | } - | |_____^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'0 u32) -> u32` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `FnOnce<(&u32,)>` - -error: implementation of `FnOnce` is not general enough - --> $DIR/higher-ranked-auto-trait-14.rs:20:5 - | -LL | / async move { -LL | | let xs = unique_x.union(&cached) -LL | | // .copied() // works -LL | | .map(|x| *x) // error -LL | | ; -LL | | let blah = val.blah(xs.into_iter()).await; -LL | | } - | |_____^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'0 u32) -> u32` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `FnOnce<(&u32,)>` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/async-await/higher-ranked-auto-trait-14.rs b/tests/ui/async-await/higher-ranked-auto-trait-14.rs index 5ed12cd6e38cb..ed53d6306c602 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-14.rs +++ b/tests/ui/async-await/higher-ranked-auto-trait-14.rs @@ -1,9 +1,8 @@ // Repro for . +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 use std::collections::HashSet; use std::future::Future; diff --git a/tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr deleted file mode 100644 index 2fc44412b9dae..0000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr +++ /dev/null @@ -1,49 +0,0 @@ -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-2.rs:16:9 - | -LL | / async move { -LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics -LL | | self.run(t).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-2.rs:16:9 - | -LL | / async move { -LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics -LL | | self.run(t).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-2.rs:16:9 - | -LL | / async move { -LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics -LL | | self.run(t).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-2.rs:16:9 - | -LL | / async move { -LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics -LL | | self.run(t).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors - diff --git a/tests/ui/async-await/higher-ranked-auto-trait-2.rs b/tests/ui/async-await/higher-ranked-auto-trait-2.rs index 6c75597265bc2..b09b4983de296 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-2.rs +++ b/tests/ui/async-await/higher-ranked-auto-trait-2.rs @@ -1,9 +1,8 @@ // Repro for . +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 use std::future::Future; diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr deleted file mode 100644 index c5c98ac807ea9..0000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:66:9 - | -LL | / async { -LL | | self.fi_2.get_iter(cx).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: aborting due to 1 previous error - diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.rs b/tests/ui/async-await/higher-ranked-auto-trait-3.rs index d42d423668051..2b7990d5f3f12 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-3.rs +++ b/tests/ui/async-await/higher-ranked-auto-trait-3.rs @@ -1,9 +1,8 @@ // Repro for . +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr deleted file mode 100644 index dcb8075566e6d..0000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `S` does not live long enough - --> $DIR/higher-ranked-auto-trait-7.rs:26:5 - | -LL | future::<'a, S, _>(async move { - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/async-await/higher-ranked-auto-trait-7.rs b/tests/ui/async-await/higher-ranked-auto-trait-7.rs index abded5a88d3ae..558bd6de44293 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-7.rs +++ b/tests/ui/async-await/higher-ranked-auto-trait-7.rs @@ -1,9 +1,8 @@ // Repro for . +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 #![allow(dropping_copy_types)] diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs index fd3ed8f18265e..55d430a08aadb 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs @@ -8,8 +8,8 @@ extern "C" { } const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; -//~^ ERROR `extern type` does not have known layout +//~^ ERROR: the size for values of type `Opaque` cannot be known const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) }; -//~^ ERROR `extern type` does not have known layout +//~^ ERROR: the size for values of type `Opaque` cannot be known fn main() {} diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr index 23f7aaf538edc..825b9e941584c 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr @@ -1,15 +1,39 @@ -error[E0080]: `extern type` does not have known layout - --> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:31 +error[E0277]: the size for values of type `Opaque` cannot be known + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:43 | LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_SIZE` failed here + | ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque` + | | + | required by a bound introduced by this call + | + = note: the trait bound `Opaque: MetaSized` is not satisfied +note: required by a bound in `std::intrinsics::size_of_val` + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL +help: consider borrowing here + | +LL | const _SIZE: usize = unsafe { size_of_val(&(&4 as *const i32 as *const Opaque)) }; + | ++ + +LL | const _SIZE: usize = unsafe { size_of_val(&mut (&4 as *const i32 as *const Opaque)) }; + | ++++++ + -error[E0080]: `extern type` does not have known layout - --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32 +error[E0277]: the size for values of type `Opaque` cannot be known + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:45 | LL | const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_ALIGN` failed here + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque` + | | + | required by a bound introduced by this call + | + = note: the trait bound `Opaque: MetaSized` is not satisfied +note: required by a bound in `std::intrinsics::align_of_val` + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL +help: consider borrowing here + | +LL | const _ALIGN: usize = unsafe { align_of_val(&(&4 as *const i32 as *const Opaque)) }; + | ++ + +LL | const _ALIGN: usize = unsafe { align_of_val(&mut (&4 as *const i32 as *const Opaque)) }; + | ++++++ + error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs index d59fc1712ea7e..8243803c86d70 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs +++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs @@ -9,7 +9,8 @@ trait Bop { fn bop() { let _ = ::Bar::default(); - //~^ ERROR: trait bounds were not satisfied + //~^ ERROR: the size for values of type `T` cannot be known at compilation time + //~| ERROR: the size for values of type `T` cannot be known at compilation time //~| ERROR: the size for values of type `T` cannot be known at compilation time } diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr index 7b152adea4925..fe048c87775a9 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr @@ -24,21 +24,58 @@ help: consider relaxing the implicit `Sized` restriction LL | type Bar: Default + ?Sized | ++++++++ -error[E0599]: the function or associated item `default` exists for associated type `::Bar`, but its trait bounds were not satisfied - --> $DIR/assoc_type_bounds_sized_used.rs:11:30 +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/assoc_type_bounds_sized_used.rs:11:13 | +LL | fn bop() { + | - this type parameter needs to be `Sized` LL | let _ = ::Bar::default(); - | ^^^^^^^ function or associated item cannot be called on `::Bar` due to unsatisfied trait bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Bop::Bar` + --> $DIR/assoc_type_bounds_sized_used.rs:7:15 + | +LL | type Bar: Default + | --- required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bop::Bar` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn bop() { +LL + fn bop() { | - = note: the following trait bounds were not satisfied: - `T: Sized` - which is required by `::Bar: Default` -help: consider restricting the type parameter to satisfy the trait bound +help: consider relaxing the implicit `Sized` restriction + | +LL | type Bar: Default + ?Sized + | ++++++++ + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/assoc_type_bounds_sized_used.rs:11:13 | -LL | fn bop() where T: Sized { - | ++++++++++++++ +LL | fn bop() { + | - this type parameter needs to be `Sized` +LL | let _ = ::Bar::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Bop::Bar` + --> $DIR/assoc_type_bounds_sized_used.rs:7:15 + | +LL | type Bar: Default + | --- required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bop::Bar` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn bop() { +LL + fn bop() { + | +help: consider relaxing the implicit `Sized` restriction + | +LL | type Bar: Default + ?Sized + | ++++++++ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0599. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/extern-types-size_of_val.rs b/tests/ui/extern/extern-types-size_of_val.rs index 875ae9a535a7a..6be33e90178fe 100644 --- a/tests/ui/extern/extern-types-size_of_val.rs +++ b/tests/ui/extern/extern-types-size_of_val.rs @@ -1,8 +1,9 @@ -//@ check-pass #![feature(extern_types)] use std::mem::{align_of_val, size_of_val}; +// Check that calls to `size_of_val` and `align_of_val` with extern types are not accepted + extern "C" { type A; } @@ -11,5 +12,7 @@ fn main() { let x: &A = unsafe { &*(1usize as *const A) }; size_of_val(x); + //~^ ERROR: the size for values of type `A` cannot be known align_of_val(x); + //~^ ERROR: the size for values of type `A` cannot be known } diff --git a/tests/ui/extern/extern-types-size_of_val.stderr b/tests/ui/extern/extern-types-size_of_val.stderr new file mode 100644 index 0000000000000..44282c3c99a19 --- /dev/null +++ b/tests/ui/extern/extern-types-size_of_val.stderr @@ -0,0 +1,39 @@ +error[E0277]: the size for values of type `A` cannot be known + --> $DIR/extern-types-size_of_val.rs:14:17 + | +LL | size_of_val(x); + | ----------- ^ the trait `MetaSized` is not implemented for `A` + | | + | required by a bound introduced by this call + | + = note: the trait bound `A: MetaSized` is not satisfied +note: required by a bound in `std::mem::size_of_val` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider borrowing here + | +LL | size_of_val(&x); + | + +LL | size_of_val(&mut x); + | ++++ + +error[E0277]: the size for values of type `A` cannot be known + --> $DIR/extern-types-size_of_val.rs:16:18 + | +LL | align_of_val(x); + | ------------ ^ the trait `MetaSized` is not implemented for `A` + | | + | required by a bound introduced by this call + | + = note: the trait bound `A: MetaSized` is not satisfied +note: required by a bound in `std::mem::align_of_val` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider borrowing here + | +LL | align_of_val(&x); + | + +LL | align_of_val(&mut x); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/extern-types-unsized.rs b/tests/ui/extern/extern-types-unsized.rs index 94a222a7e7e01..6d6407fb0661c 100644 --- a/tests/ui/extern/extern-types-unsized.rs +++ b/tests/ui/extern/extern-types-unsized.rs @@ -27,7 +27,9 @@ fn main() { assert_sized::>(); //~^ ERROR the size for values of type + //~| ERROR the size for values of type `A` cannot be known assert_sized::>>(); //~^ ERROR the size for values of type + //~| ERROR the size for values of type `A` cannot be known } diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index a587d4dda55c8..43dd9800d6d30 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -59,8 +59,21 @@ help: consider relaxing the implicit `Sized` restriction LL | fn assert_sized() {} | ++++++++ +error[E0277]: the size for values of type `A` cannot be known + --> $DIR/extern-types-unsized.rs:28:20 + | +LL | assert_sized::>(); + | ^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `A` +note: required by a bound in `Bar` + --> $DIR/extern-types-unsized.rs:14:12 + | +LL | struct Bar { + | ^ required by this bound in `Bar` + error[E0277]: the size for values of type `A` cannot be known at compilation time - --> $DIR/extern-types-unsized.rs:31:20 + --> $DIR/extern-types-unsized.rs:32:20 | LL | assert_sized::>>(); | ^^^^^^^^^^^ doesn't have a size known at compile-time @@ -81,6 +94,19 @@ help: consider relaxing the implicit `Sized` restriction LL | fn assert_sized() {} | ++++++++ -error: aborting due to 4 previous errors +error[E0277]: the size for values of type `A` cannot be known + --> $DIR/extern-types-unsized.rs:32:20 + | +LL | assert_sized::>>(); + | ^^^^^^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `A` +note: required by a bound in `Bar` + --> $DIR/extern-types-unsized.rs:14:12 + | +LL | struct Bar { + | ^ required by this bound in `Bar` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/unsized-extern-derefmove.rs b/tests/ui/extern/unsized-extern-derefmove.rs index 39597a12fe117..c02375266ab47 100644 --- a/tests/ui/extern/unsized-extern-derefmove.rs +++ b/tests/ui/extern/unsized-extern-derefmove.rs @@ -7,10 +7,14 @@ extern "C" { } unsafe fn make_device() -> Box { +//~^ ERROR the size for values of type `Device` cannot be known Box::from_raw(0 as *mut _) +//~^ ERROR the size for values of type `Device` cannot be known +//~| ERROR the size for values of type `Device` cannot be known } fn main() { let d: Device = unsafe { *make_device() }; //~^ ERROR the size for values of type `Device` cannot be known +//~| ERROR the size for values of type `Device` cannot be known } diff --git a/tests/ui/extern/unsized-extern-derefmove.stderr b/tests/ui/extern/unsized-extern-derefmove.stderr index c43184d94e177..a9efc2e66e3b0 100644 --- a/tests/ui/extern/unsized-extern-derefmove.stderr +++ b/tests/ui/extern/unsized-extern-derefmove.stderr @@ -1,5 +1,43 @@ +error[E0277]: the size for values of type `Device` cannot be known + --> $DIR/unsized-extern-derefmove.rs:9:28 + | +LL | unsafe fn make_device() -> Box { + | ^^^^^^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `Device` +note: required by a bound in `Box` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error[E0277]: the size for values of type `Device` cannot be known + --> $DIR/unsized-extern-derefmove.rs:11:19 + | +LL | Box::from_raw(0 as *mut _) + | ------------- ^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Device` + | | + | required by a bound introduced by this call + | + = note: the trait bound `Device: MetaSized` is not satisfied +note: required by a bound in `Box::::from_raw` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: consider borrowing here + | +LL | Box::from_raw(&(0 as *mut _)) + | ++ + +LL | Box::from_raw(&mut (0 as *mut _)) + | ++++++ + + +error[E0277]: the size for values of type `Device` cannot be known + --> $DIR/unsized-extern-derefmove.rs:11:5 + | +LL | Box::from_raw(0 as *mut _) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `Device` +note: required by a bound in `Box` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + error[E0277]: the size for values of type `Device` cannot be known at compilation time - --> $DIR/unsized-extern-derefmove.rs:14:9 + --> $DIR/unsized-extern-derefmove.rs:17:9 | LL | let d: Device = unsafe { *make_device() }; | ^ doesn't have a size known at compile-time @@ -11,6 +49,16 @@ help: consider borrowing here LL | let d: &Device = unsafe { *make_device() }; | + -error: aborting due to 1 previous error +error[E0277]: the size for values of type `Device` cannot be known + --> $DIR/unsized-extern-derefmove.rs:17:31 + | +LL | let d: Device = unsafe { *make_device() }; + | ^^^^^^^^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `Device` +note: required by a bound in `Box` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr deleted file mode 100644 index 8b62fb6a25473..0000000000000 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: lifetime bound not satisfied - --> $DIR/higher-ranked-coroutine-param-outlives-2.rs:14:5 - | -LL | / async { // a coroutine checked for autotrait impl `Send` -LL | | let x = None::>; // a type referencing GAT -LL | | async {}.await; // a yield point -LL | | } - | |_____^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-coroutine-param-outlives-2.rs:21:5 - | -LL | / async { // a coroutine checked for autotrait impl `Send` -LL | | let x = None::>; // a type referencing GAT -LL | | async {}.await; // a yield point -LL | | } - | |_____^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: aborting due to 2 previous errors - diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs index a5ed162d62c90..96ff23cbc0870 100644 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs +++ b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs @@ -1,8 +1,7 @@ +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 pub trait FutureIterator { type Future<'s, 'cx>: Send diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr deleted file mode 100644 index f747ba9a73341..0000000000000 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `C` does not live long enough - --> $DIR/higher-ranked-coroutine-param-outlives.rs:21:5 - | -LL | async move { c.connect().await } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs index 5f683bd82fa46..0c7d29d1256ad 100644 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs +++ b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs @@ -1,8 +1,7 @@ +//@ check-pass //@ edition:2018 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 use std::future::Future; diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr new file mode 100644 index 0000000000000..723dd097f9b97 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `>::Out<_>` + --> $DIR/norm-before-method-resolution-opaque-type.rs:25:9 + | +LL | let x = *x; + | ^ + | +help: consider giving `x` an explicit type, where the placeholders `_` are specified + | +LL | let x: <_ as Trait<'static>>::Out<_> = *x; + | +++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr index 79ded34d9cd9e..d8b94fd4f7d1b 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `*x` which is behind a shared reference - --> $DIR/norm-before-method-resolution-opaque-type.rs:22:13 + --> $DIR/norm-before-method-resolution-opaque-type.rs:25:13 | LL | let x = *x; | ^^ move occurs because `*x` has type `>::Out`, which does not implement the `Copy` trait diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs index f881fcb779fa8..55e99171ea633 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs @@ -1,6 +1,9 @@ //@ revisions: old next //@[next] compile-flags: -Znext-solver -//@[next] check-pass + +// In the next solver, the opaque was previously defined by using the where-bound when checking +// whether the alias is `Sized`, constraining the opaque. Instead, the alias-bound is now used, +// which means the opaque is never constrained. #![feature(type_alias_impl_trait)] trait Trait<'a> { @@ -20,6 +23,7 @@ where for<'a> >::Out<()>: Copy, { let x = *x; //[old]~ ERROR: cannot move out of `*x` + //[next]~^ ERROR: type annotations needed todo!(); } diff --git a/tests/ui/layout/unconstrained-param-ice-137308.rs b/tests/ui/layout/unconstrained-param-ice-137308.rs index d05e6e1fd3f33..03b7e7599601a 100644 --- a/tests/ui/layout/unconstrained-param-ice-137308.rs +++ b/tests/ui/layout/unconstrained-param-ice-137308.rs @@ -17,3 +17,4 @@ impl A for u8 { //~ ERROR: the type parameter `C` is not constrained #[rustc_layout(debug)] struct S([u8; ::B]); //~^ ERROR: the type has an unknown layout +//~| ERROR: type annotations needed diff --git a/tests/ui/layout/unconstrained-param-ice-137308.stderr b/tests/ui/layout/unconstrained-param-ice-137308.stderr index 615c131eb9045..82cd1217c4903 100644 --- a/tests/ui/layout/unconstrained-param-ice-137308.stderr +++ b/tests/ui/layout/unconstrained-param-ice-137308.stderr @@ -4,12 +4,19 @@ error[E0207]: the type parameter `C` is not constrained by the impl trait, self LL | impl A for u8 { | ^ unconstrained type parameter +error[E0282]: type annotations needed + --> $DIR/unconstrained-param-ice-137308.rs:18:16 + | +LL | struct S([u8; ::B]); + | ^^ cannot infer type for type parameter `C` + error: the type has an unknown layout --> $DIR/unconstrained-param-ice-137308.rs:18:1 | LL | struct S([u8; ::B]); | ^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs b/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs new file mode 100644 index 0000000000000..4a20ed2cafb16 --- /dev/null +++ b/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs @@ -0,0 +1,21 @@ +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + +use std::marker::PhantomData; + +pub trait ZeroMapKV<'a> { + type Container; +} + +pub trait ZeroFrom<'zf, C: ?Sized> {} + +pub struct ZeroMap<'a, K: ZeroMapKV<'a>>(PhantomData<&'a K>); + +impl<'zf, 's, K> ZeroFrom<'zf, ZeroMap<'s, K>> for ZeroMap<'zf, K> +where + K: for<'b> ZeroMapKV<'b>, + >::Container: ZeroFrom<'zf, >::Container>, +{ +} diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr deleted file mode 100644 index b904b784df735..0000000000000 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/incomplete-inference-issue-143992.rs:30:28 - | -LL | let _x = T::Assoc::new(()); - | ------------- ^^ expected `[u32; 1]`, found `()` - | | - | arguments to this function are incorrect - | -note: associated function defined here - --> $DIR/incomplete-inference-issue-143992.rs:21:8 - | -LL | fn new(r: R) -> R { - | ^^^ ---- - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr deleted file mode 100644 index b904b784df735..0000000000000 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/incomplete-inference-issue-143992.rs:30:28 - | -LL | let _x = T::Assoc::new(()); - | ------------- ^^ expected `[u32; 1]`, found `()` - | | - | arguments to this function are incorrect - | -note: associated function defined here - --> $DIR/incomplete-inference-issue-143992.rs:21:8 - | -LL | fn new(r: R) -> R { - | ^^^ ---- - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs index b9e65ed283935..44453b65e7cd1 100644 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs +++ b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs @@ -1,12 +1,8 @@ +//@ check-pass //@ compile-flags: --crate-type=lib -//@ revisions: current next current_sized_hierarchy next_sized_hierarchy +//@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) -//@[current] check-pass -//@[next] check-pass //@[next] compile-flags: -Znext-solver -//@[next_sized_hierarchy] compile-flags: -Znext-solver - -#![cfg_attr(any(current_sized_hierarchy, next_sized_hierarchy), feature(sized_hierarchy))] // Test that we avoid incomplete inference when normalizing. Without this, // `Trait`'s implicit `MetaSized` supertrait requires proving `T::Assoc<_>: MetaSized` @@ -28,6 +24,4 @@ where T::Assoc<[u32; 1]>: Clone, { let _x = T::Assoc::new(()); - //[next_sized_hierarchy]~^ ERROR mismatched types - //[current_sized_hierarchy]~^^ ERROR mismatched types } diff --git a/tests/ui/sized-hierarchy/overflow.current.stderr b/tests/ui/sized-hierarchy/overflow.current.stderr new file mode 100644 index 0000000000000..da58a6d2f7bf6 --- /dev/null +++ b/tests/ui/sized-hierarchy/overflow.current.stderr @@ -0,0 +1,45 @@ +error[E0275]: overflow evaluating the requirement `Element: MetaSized` + --> $DIR/overflow.rs:17:16 + | +LL | struct Element(> as ParseTokens>::Output); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required for `Box` to implement `ParseTokens` + --> $DIR/overflow.rs:13:31 + | +LL | impl ParseTokens for Box { + | - ^^^^^^^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `Box>` to implement `ParseTokens` + +error[E0275]: overflow evaluating the requirement `Box: ParseTokens` + --> $DIR/overflow.rs:19:22 + | +LL | impl ParseTokens for Element { + | ^^^^^^^ + | +note: required for `Box>` to implement `ParseTokens` + --> $DIR/overflow.rs:13:31 + | +LL | impl ParseTokens for Box { + | ----------- ^^^^^^^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required because it appears within the type `Element` + --> $DIR/overflow.rs:17:8 + | +LL | struct Element(> as ParseTokens>::Output); + | ^^^^^^^ +note: required by a bound in `ParseTokens` + --> $DIR/overflow.rs:10:1 + | +LL | / trait ParseTokens { +LL | | type Output; +LL | | } + | |_^ required by this bound in `ParseTokens` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/sized-hierarchy/overflow.rs b/tests/ui/sized-hierarchy/overflow.rs index f8e5dd5d4029b..31c2ca8a49171 100644 --- a/tests/ui/sized-hierarchy/overflow.rs +++ b/tests/ui/sized-hierarchy/overflow.rs @@ -1,13 +1,10 @@ //@ compile-flags: --crate-type=lib //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) -//@[current] check-pass +//@[current] check-fail //@[next] check-pass //@[next] compile-flags: -Znext-solver -// FIXME(sized_hierarchy): this is expected to fail in the old solver when there -// isn't a temporary revert of the `sized_hierarchy` feature - use std::marker::PhantomData; trait ParseTokens { @@ -18,6 +15,8 @@ impl ParseTokens for Box { } struct Element(> as ParseTokens>::Output); +//[current]~^ ERROR: overflow impl ParseTokens for Element { +//[current]~^ ERROR: overflow type Output = (); } diff --git a/tests/ui/sized-hierarchy/prefer-non-nested-alias-bound.rs b/tests/ui/sized-hierarchy/prefer-non-nested-alias-bound.rs new file mode 100644 index 0000000000000..affef2e61482e --- /dev/null +++ b/tests/ui/sized-hierarchy/prefer-non-nested-alias-bound.rs @@ -0,0 +1,30 @@ +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Since #120752, also get alias-bound candidates from a nested self-type, so prefering +// alias-bound over where-bound candidates can be incorrect. This test checks that case and that +// we prefer non-nested alias-bound candidates over where-bound candidates over nested alias-bound +// candidates. + +trait OtherTrait<'a> { + type Assoc: ?Sized; +} + +trait Trait +where + >::Assoc: Sized, +{ + type Assoc: for<'a> OtherTrait<'a>; +} + +fn impls_sized() {} +fn foo<'a, T>() +where + T: Trait, + for<'hr> >::Assoc: Sized, +{ + impls_sized::<>::Assoc>(); +} diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr index 4934d8bf6fa07..4a87aa3e2f128 100644 --- a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr @@ -17,6 +17,13 @@ LL | impl Trait for T { | ----- ^^^^^^^^ ^ | | | unsatisfied trait bound introduced here +note: required by a bound in `Bound` + --> $DIR/normalizes-to-is-not-productive.rs:8:1 + | +LL | / trait Bound { +LL | | fn method(); +LL | | } + | |_^ required by this bound in `Bound` error[E0277]: the trait bound `Foo: Bound` is not satisfied --> $DIR/normalizes-to-is-not-productive.rs:47:19 diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index d179c80596238..8d8909625ffc8 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -19,6 +19,23 @@ error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` LL | Self::Assoc: A, | ^^^^ +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: MetaSized` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A, + | ^^^^ + | +note: required by a bound in `A` + --> $DIR/normalize-param-env-2.rs:9:1 + | +LL | / trait A { +LL | | type Assoc; +LL | | +LL | | fn f() +... | +LL | | } + | |_^ required by this bound in `A` + error[E0275]: overflow evaluating the requirement `<() as A>::Assoc well-formed` --> $DIR/normalize-param-env-2.rs:24:22 | @@ -46,6 +63,6 @@ LL | where LL | Self::Assoc: A, | ^^^^ required by this bound in `A::f` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index f5fd9ce9864ce..9f7f74f94664b 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -4,6 +4,20 @@ error[E0275]: overflow evaluating the requirement `::Assoc: Trait` LL | ::Assoc: Trait, | ^^^^^ -error: aborting due to 1 previous error +error[E0275]: overflow evaluating the requirement `::Assoc: MetaSized` + --> $DIR/normalize-param-env-4.rs:19:26 + | +LL | ::Assoc: Trait, + | ^^^^^ + | +note: required by a bound in `Trait` + --> $DIR/normalize-param-env-4.rs:7:1 + | +LL | / trait Trait { +LL | | type Assoc; +LL | | } + | |_^ required by this bound in `Trait` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.rs b/tests/ui/traits/resolve-impl-before-constrain-check.rs index 87f9c241e402b..00005a7209363 100644 --- a/tests/ui/traits/resolve-impl-before-constrain-check.rs +++ b/tests/ui/traits/resolve-impl-before-constrain-check.rs @@ -15,6 +15,7 @@ use foo::*; fn test() -> impl Sized { <() as Callable>::call() +//~^ ERROR type annotations needed } fn main() {} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.stderr b/tests/ui/traits/resolve-impl-before-constrain-check.stderr index e8e569ba625ee..13fbfdb855cbf 100644 --- a/tests/ui/traits/resolve-impl-before-constrain-check.stderr +++ b/tests/ui/traits/resolve-impl-before-constrain-check.stderr @@ -4,6 +4,13 @@ error[E0207]: the type parameter `V` is not constrained by the impl trait, self LL | impl Callable for () { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/resolve-impl-before-constrain-check.rs:17:6 + | +LL | <() as Callable>::call() + | ^^ cannot infer type for type parameter `V` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`.