diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 89f62577506fd..0ba4bd090f5e2 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1741,7 +1741,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } PatKind::Slice(before, ref slice, after) => { - let Some(element_ty) = place_with_id.place.ty().builtin_index() else { + let Some(element_ty) = self + .cx + .try_structurally_resolve_type(pat.span, place_with_id.place.ty()) + .builtin_index() + else { debug!("explicit index of non-indexable type {:?}", place_with_id); return Err(self .cx diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 36f9dda7250ca..c6cf7cf4f3f7d 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -799,10 +799,7 @@ fn test_unstable_options_tracking_hash() { tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, false); - tracked!( - next_solver, - Some(NextSolverConfig { coherence: true, globally: false, dump_tree: Default::default() }) - ); + tracked!(next_solver, Some(NextSolverConfig { coherence: true, globally: false })); tracked!(no_generate_arange_section, true); tracked!(no_jump_tables, true); tracked!(no_link, true); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index a9304f27fe557..21c7c5bb8b217 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -233,6 +233,7 @@ lint_drop_trait_constraints = lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result + .suggestion = use `let _ = ...` to ignore the expression or result lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 60b799f3c7468..02d324520b859 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -1,12 +1,12 @@ -use rustc_hir::{Arm, Expr, ExprKind, Node}; +use rustc_hir::{Arm, Expr, ExprKind, Node, StmtKind}; use rustc_middle::ty; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; use crate::{ lints::{ - DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag, - UndroppedManuallyDropsSuggestion, + DropCopyDiag, DropCopySuggestion, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, + UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, }, LateContext, LateLintPass, LintContext, }; @@ -164,10 +164,23 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { ); } sym::mem_drop if is_copy && !drop_is_single_call_in_arm => { + let sugg = if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) + && let Node::Stmt(stmt) = node + && let StmtKind::Semi(e) = stmt.kind + && e.hir_id == expr.hir_id + { + DropCopySuggestion::Suggestion { + start_span: expr.span.shrink_to_lo().until(arg.span), + end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + } + } else { + DropCopySuggestion::Note + }; + cx.emit_span_lint( DROPPING_COPY_TYPES, expr.span, - DropCopyDiag { arg_ty, label: arg.span }, + DropCopyDiag { arg_ty, label: arg.span, sugg }, ); } sym::mem_forget if is_copy => { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 2f44bc4764e33..87ca1ccd104e3 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -677,11 +677,25 @@ pub struct DropRefDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_dropping_copy_types)] -#[note] pub struct DropCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: DropCopySuggestion, +} + +#[derive(Subdiagnostic)] +pub enum DropCopySuggestion { + #[note(lint_note)] + Note, + #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + Suggestion { + #[suggestion_part(code = "let _ = ")] + start_span: Span, + #[suggestion_part(code = "")] + end_span: Span, + }, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 7392eb6c2bb4d..b0e72eaf5a4cd 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -61,7 +61,10 @@ macro_rules! arena_types { [] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>, [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>, [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>, - [] canonical_goal_evaluation: rustc_next_trait_solver::solve::inspect::GoalEvaluationStep>, + [] canonical_goal_evaluation: + rustc_next_trait_solver::solve::inspect::CanonicalGoalEvaluationStep< + rustc_middle::ty::TyCtxt<'tcx> + >, [] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>, [] type_op_subtype: rustc_middle::infer::canonical::Canonical<'tcx, diff --git a/compiler/rustc_middle/src/traits/solve/cache.rs b/compiler/rustc_middle/src/traits/solve/cache.rs index 2ff4ade21d087..dc31114b2c459 100644 --- a/compiler/rustc_middle/src/traits/solve/cache.rs +++ b/compiler/rustc_middle/src/traits/solve/cache.rs @@ -17,7 +17,7 @@ pub struct EvaluationCache<'tcx> { #[derive(Debug, PartialEq, Eq)] pub struct CacheData<'tcx> { pub result: QueryResult<'tcx>, - pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep>]>, + pub proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep>>, pub additional_depth: usize, pub encountered_overflow: bool, } @@ -28,7 +28,7 @@ impl<'tcx> EvaluationCache<'tcx> { &self, tcx: TyCtxt<'tcx>, key: CanonicalInput<'tcx>, - proof_tree: Option<&'tcx [inspect::GoalEvaluationStep>]>, + proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep>>, additional_depth: usize, encountered_overflow: bool, cycle_participants: FxHashSet>, @@ -107,7 +107,7 @@ struct Success<'tcx> { #[derive(Clone, Copy)] pub struct QueryData<'tcx> { pub result: QueryResult<'tcx>, - pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep>]>, + pub proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep>>, } /// The cache entry for a goal `CanonicalInput`. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6e53b5bb52067..d138cd9ceb9d4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -103,7 +103,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; type DefiningOpaqueTypes = &'tcx ty::List; type ExternalConstraints = ExternalConstraints<'tcx>; - type GoalEvaluationSteps = &'tcx [solve::inspect::GoalEvaluationStep>]; + type CanonicalGoalEvaluationStepRef = + &'tcx solve::inspect::CanonicalGoalEvaluationStep>; type Ty = Ty<'tcx>; type Tys = &'tcx List>; diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 93d0d4e59ba99..4b62afa61bbd5 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -4,7 +4,6 @@ use crate::build::expr::category::Category; use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder, Capture, CaptureMap}; use rustc_hir::def_id::LocalDefId; -use rustc_middle::bug; use rustc_middle::hir::place::Projection as HirProjection; use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::middle::region; @@ -13,6 +12,7 @@ use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::AdtDef; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance}; +use rustc_middle::{bug, span_bug}; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use tracing::{debug, instrument, trace}; @@ -252,7 +252,18 @@ fn strip_prefix<'a, 'tcx>( impl<'tcx> PlaceBuilder<'tcx> { pub(in crate::build) fn to_place(&self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> { - self.try_to_place(cx).unwrap() + self.try_to_place(cx).unwrap_or_else(|| match self.base { + PlaceBase::Local(local) => span_bug!( + cx.local_decls[local].source_info.span, + "could not resolve local: {local:#?} + {:?}", + self.projection + ), + PlaceBase::Upvar { var_hir_id, closure_def_id: _ } => span_bug!( + cx.tcx.hir().span(var_hir_id.0), + "could not resolve upvar: {var_hir_id:?} + {:?}", + self.projection + ), + }) } /// Creates a `Place` or returns `None` if an upvar cannot be resolved diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 76972ff2263d8..9487692662bb7 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1434,6 +1434,15 @@ impl<'v> RootCollector<'_, 'v> { { debug!("RootCollector: ADT drop-glue for `{id:?}`",); + // This type is impossible to instantiate, so we should not try to + // generate a `drop_in_place` instance for it. + if self.tcx.instantiate_and_check_impossible_predicates(( + id.owner_id.to_def_id(), + ty::List::empty(), + )) { + return; + } + let ty = self.tcx.type_of(id.owner_id.to_def_id()).no_bound_vars().unwrap(); visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 5ac4d194e8721..c90da966e7081 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -796,16 +796,6 @@ pub struct NextSolverConfig { /// Whether the new trait solver should be enabled everywhere. /// This is only `true` if `coherence` is also enabled. pub globally: bool, - /// Whether to dump proof trees after computing a proof tree. - pub dump_tree: DumpSolverProofTree, -} - -#[derive(Default, Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub enum DumpSolverProofTree { - Always, - OnError, - #[default] - Never, } #[derive(Clone)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 65660286dd73a..6309fcdd2db3c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -399,7 +399,8 @@ mod desc { pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; - pub const parse_next_solver_config: &str = "a comma separated list of solver configurations: `globally` (default), `coherence`, `dump-tree`, `dump-tree-on-error"; + pub const parse_next_solver_config: &str = + "a comma separated list of solver configurations: `globally` (default), and `coherence`"; pub const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub const parse_linker_plugin_lto: &str = @@ -1058,7 +1059,6 @@ mod parse { if let Some(config) = v { let mut coherence = false; let mut globally = true; - let mut dump_tree = None; for c in config.split(',') { match c { "globally" => globally = true, @@ -1066,31 +1066,13 @@ mod parse { globally = false; coherence = true; } - "dump-tree" => { - if dump_tree.replace(DumpSolverProofTree::Always).is_some() { - return false; - } - } - "dump-tree-on-error" => { - if dump_tree.replace(DumpSolverProofTree::OnError).is_some() { - return false; - } - } _ => return false, } } - *slot = Some(NextSolverConfig { - coherence: coherence || globally, - globally, - dump_tree: dump_tree.unwrap_or_default(), - }); + *slot = Some(NextSolverConfig { coherence: coherence || globally, globally }); } else { - *slot = Some(NextSolverConfig { - coherence: true, - globally: true, - dump_tree: Default::default(), - }); + *slot = Some(NextSolverConfig { coherence: true, globally: true }); } true diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 1b507bb2a155e..d9812540e497d 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -199,11 +199,9 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("avx512bw", Unstable(sym::avx512_target_feature)), ("avx512cd", Unstable(sym::avx512_target_feature)), ("avx512dq", Unstable(sym::avx512_target_feature)), - ("avx512er", Unstable(sym::avx512_target_feature)), ("avx512f", Unstable(sym::avx512_target_feature)), ("avx512fp16", Unstable(sym::avx512_target_feature)), ("avx512ifma", Unstable(sym::avx512_target_feature)), - ("avx512pf", Unstable(sym::avx512_target_feature)), ("avx512vbmi", Unstable(sym::avx512_target_feature)), ("avx512vbmi2", Unstable(sym::avx512_target_feature)), ("avx512vl", Unstable(sym::avx512_target_feature)), diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 7e1d7d73e0b3f..ce408ddea3780 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -1,6 +1,3 @@ -use std::io::Write; -use std::ops::ControlFlow; - use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; @@ -20,10 +17,10 @@ use rustc_middle::ty::{ self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_session::config::DumpSolverProofTree; use rustc_span::DUMMY_SP; use rustc_type_ir::{self as ir, CanonicalVarValues, Interner}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; +use std::ops::ControlFlow; use crate::traits::coherence; use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment}; @@ -135,8 +132,7 @@ impl NestedGoals { #[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)] pub enum GenerateProofTree { Yes, - IfEnabled, - Never, + No, } #[extension(pub trait InferCtxtEvalExt<'tcx>)] @@ -182,7 +178,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { infcx, search_graph: &mut search_graph, nested_goals: NestedGoals::new(), - inspect: ProofTreeBuilder::new_maybe_root(infcx.tcx, generate_proof_tree), + inspect: ProofTreeBuilder::new_maybe_root(generate_proof_tree), // Only relevant when canonicalizing the response, // which we don't do within this evaluation context. @@ -197,23 +193,14 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { }; let result = f(&mut ecx); - let tree = ecx.inspect.finalize(); - if let (Some(tree), DumpSolverProofTree::Always) = ( - &tree, - infcx.tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default(), - ) { - let mut lock = std::io::stdout().lock(); - let _ = lock.write_fmt(format_args!("{tree:?}\n")); - let _ = lock.flush(); - } - + let proof_tree = ecx.inspect.finalize(); assert!( ecx.nested_goals.is_empty(), "root `EvalCtxt` should not have any goals added to it" ); assert!(search_graph.is_empty()); - (result, tree) + (result, proof_tree) } /// Creates a nested evaluation context that shares the same search graph as the @@ -483,7 +470,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { // the certainty of all the goals. #[instrument(level = "trace", skip(self))] pub(super) fn try_evaluate_added_goals(&mut self) -> Result { - self.inspect.start_evaluate_added_goals(); let mut response = Ok(Certainty::overflow(false)); for _ in 0..FIXPOINT_STEP_LIMIT { // FIXME: This match is a bit ugly, it might be nice to change the inspect @@ -501,8 +487,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { } } - self.inspect.evaluate_added_goals_result(response); - if response.is_err() { self.tainted = Err(NoSolution); } @@ -515,7 +499,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`. fn evaluate_added_goals_step(&mut self) -> Result, NoSolution> { let tcx = self.tcx(); - self.inspect.start_evaluate_added_goals_step(); let mut goals = core::mem::take(&mut self.nested_goals); // If this loop did not result in any progress, what's our final certainty. diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 7291eb00e7271..d28cf834032de 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -79,7 +79,7 @@ impl<'tcx> ObligationStorage<'tcx> { // change. self.overflowed.extend(self.pending.extract_if(|o| { let goal = o.clone().into(); - let result = infcx.evaluate_root_goal(goal, GenerateProofTree::Never).0; + let result = infcx.evaluate_root_goal(goal, GenerateProofTree::No).0; match result { Ok((has_changed, _)) => has_changed, _ => false, @@ -159,7 +159,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { let mut has_changed = false; for obligation in self.obligations.unstalled_for_select() { let goal = obligation.clone().into(); - let result = infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0; + let result = infcx.evaluate_root_goal(goal, GenerateProofTree::No).0; self.inspect_evaluated_obligation(infcx, &obligation, &result); let (changed, certainty) = match result { Ok(result) => result, @@ -246,7 +246,7 @@ fn fulfillment_error_for_stalled<'tcx>( root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx> { let (code, refine_obligation) = infcx.probe(|_| { - match infcx.evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::Never).0 { + match infcx.evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::No).0 { Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { (FulfillmentErrorCode::Ambiguity { overflow: None }, true) } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 737d03f73f00b..447357f8b3f64 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -317,7 +317,6 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { inspect::ProbeStep::RecordImplArgs { impl_args: i } => { assert_eq!(impl_args.replace(i), None); } - inspect::ProbeStep::EvaluateGoals(_) => (), } } @@ -359,13 +358,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { warn!("unexpected root evaluation: {:?}", self.evaluation_kind); return vec![]; } - inspect::CanonicalGoalEvaluationKind::Evaluation { revisions } => { - if let Some(last) = revisions.last() { - last - } else { - return vec![]; - } - } + inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } => final_revision, }; let mut nested_goals = vec![]; @@ -392,9 +385,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { normalizes_to_term_hack: Option>, source: GoalSource, ) -> Self { - let inspect::GoalEvaluation { uncanonicalized_goal, kind, evaluation } = root; - let inspect::GoalEvaluationKind::Root { orig_values } = kind else { unreachable!() }; - + let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, evaluation } = root; let result = evaluation.result.and_then(|ok| { if let Some(term_hack) = normalizes_to_term_hack { infcx diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs index 803300c5196ca..3c63336264831 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs @@ -5,20 +5,17 @@ //! see the comment on [ProofTreeBuilder]. use std::mem; +use crate::solve::eval_ctxt::canonical; +use crate::solve::{self, inspect, GenerateProofTree}; use rustc_infer::infer::InferCtxt; use rustc_middle::bug; use rustc_middle::infer::canonical::CanonicalVarValues; -use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, TyCtxt}; use rustc_next_trait_solver::solve::{ CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult, }; -use rustc_session::config::DumpSolverProofTree; use rustc_type_ir::Interner; -use crate::solve::eval_ctxt::canonical; -use crate::solve::{self, inspect, GenerateProofTree}; - /// The core data structure when building proof trees. /// /// In case the current evaluation does not generate a proof @@ -53,7 +50,7 @@ enum DebugSolver { Root, GoalEvaluation(WipGoalEvaluation), CanonicalGoalEvaluation(WipCanonicalGoalEvaluation), - GoalEvaluationStep(WipGoalEvaluationStep), + CanonicalGoalEvaluationStep(WipCanonicalGoalEvaluationStep), } impl From> for DebugSolver { @@ -68,9 +65,9 @@ impl From> for DebugSolver { } } -impl From> for DebugSolver { - fn from(g: WipGoalEvaluationStep) -> DebugSolver { - DebugSolver::GoalEvaluationStep(g) +impl From> for DebugSolver { + fn from(g: WipCanonicalGoalEvaluationStep) -> DebugSolver { + DebugSolver::CanonicalGoalEvaluationStep(g) } } @@ -78,7 +75,7 @@ impl From> for DebugSolver { #[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] struct WipGoalEvaluation { pub uncanonicalized_goal: Goal, - pub kind: WipGoalEvaluationKind, + pub orig_values: Vec, pub evaluation: Option>, } @@ -86,31 +83,19 @@ impl WipGoalEvaluation { fn finalize(self) -> inspect::GoalEvaluation { inspect::GoalEvaluation { uncanonicalized_goal: self.uncanonicalized_goal, - kind: match self.kind { - WipGoalEvaluationKind::Root { orig_values } => { - inspect::GoalEvaluationKind::Root { orig_values } - } - WipGoalEvaluationKind::Nested => inspect::GoalEvaluationKind::Nested, - }, + orig_values: self.orig_values, evaluation: self.evaluation.unwrap().finalize(), } } } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] -pub(in crate::solve) enum WipGoalEvaluationKind { - Root { orig_values: Vec }, - Nested, -} - #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""))] pub(in crate::solve) enum WipCanonicalGoalEvaluationKind { Overflow, CycleInStack, ProvisionalCacheHit, - Interned { revisions: I::GoalEvaluationSteps }, + Interned { final_revision: I::CanonicalGoalEvaluationStepRef }, } impl std::fmt::Debug for WipCanonicalGoalEvaluationKind { @@ -119,7 +104,9 @@ impl std::fmt::Debug for WipCanonicalGoalEvaluationKind { Self::Overflow => write!(f, "Overflow"), Self::CycleInStack => write!(f, "CycleInStack"), Self::ProvisionalCacheHit => write!(f, "ProvisionalCacheHit"), - Self::Interned { revisions: _ } => f.debug_struct("Interned").finish_non_exhaustive(), + Self::Interned { final_revision: _ } => { + f.debug_struct("Interned").finish_non_exhaustive() + } } } } @@ -131,13 +118,15 @@ struct WipCanonicalGoalEvaluation { kind: Option>, /// Only used for uncached goals. After we finished evaluating /// the goal, this is interned and moved into `kind`. - revisions: Vec>, + final_revision: Option>, result: Option>, } impl WipCanonicalGoalEvaluation { fn finalize(self) -> inspect::CanonicalGoalEvaluation { - assert!(self.revisions.is_empty()); + // We've already interned the final revision in + // `fn finalize_canonical_goal_evaluation`. + assert!(self.final_revision.is_none()); let kind = match self.kind.unwrap() { WipCanonicalGoalEvaluationKind::Overflow => { inspect::CanonicalGoalEvaluationKind::Overflow @@ -148,8 +137,8 @@ impl WipCanonicalGoalEvaluation { WipCanonicalGoalEvaluationKind::ProvisionalCacheHit => { inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit } - WipCanonicalGoalEvaluationKind::Interned { revisions } => { - inspect::CanonicalGoalEvaluationKind::Evaluation { revisions } + WipCanonicalGoalEvaluationKind::Interned { final_revision } => { + inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } } }; @@ -159,29 +148,7 @@ impl WipCanonicalGoalEvaluation { #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] -struct WipAddedGoalsEvaluation { - evaluations: Vec>>, - result: Option>, -} - -impl WipAddedGoalsEvaluation { - fn finalize(self) -> inspect::AddedGoalsEvaluation { - inspect::AddedGoalsEvaluation { - evaluations: self - .evaluations - .into_iter() - .map(|evaluations| { - evaluations.into_iter().map(WipGoalEvaluation::finalize).collect() - }) - .collect(), - result: self.result.unwrap(), - } - } -} - -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] -struct WipGoalEvaluationStep { +struct WipCanonicalGoalEvaluationStep { /// Unlike `EvalCtxt::var_values`, we append a new /// generic arg here whenever we create a new inference /// variable. @@ -194,7 +161,7 @@ struct WipGoalEvaluationStep { evaluation: WipProbe, } -impl WipGoalEvaluationStep { +impl WipCanonicalGoalEvaluationStep { fn current_evaluation_scope(&mut self) -> &mut WipProbe { let mut current = &mut self.evaluation; for _ in 0..self.probe_depth { @@ -206,24 +173,16 @@ impl WipGoalEvaluationStep { current } - fn added_goals_evaluation(&mut self) -> &mut WipAddedGoalsEvaluation { - let mut current = &mut self.evaluation; - loop { - match current.steps.last_mut() { - Some(WipProbeStep::NestedProbe(p)) => current = p, - Some(WipProbeStep::EvaluateGoals(evaluation)) => return evaluation, - _ => bug!(), - } - } - } - - fn finalize(self) -> inspect::GoalEvaluationStep { + fn finalize(self) -> inspect::CanonicalGoalEvaluationStep { let evaluation = self.evaluation.finalize(); match evaluation.kind { inspect::ProbeKind::Root { .. } => (), _ => unreachable!("unexpected root evaluation: {evaluation:?}"), } - inspect::GoalEvaluationStep { instantiated_goal: self.instantiated_goal, evaluation } + inspect::CanonicalGoalEvaluationStep { + instantiated_goal: self.instantiated_goal, + evaluation, + } } } @@ -250,7 +209,6 @@ impl WipProbe { #[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] enum WipProbeStep { AddGoal(GoalSource, inspect::CanonicalState>), - EvaluateGoals(WipAddedGoalsEvaluation), NestedProbe(WipProbe), MakeCanonicalResponse { shallow_certainty: Certainty }, RecordImplArgs { impl_args: inspect::CanonicalState }, @@ -260,7 +218,6 @@ impl WipProbeStep { fn finalize(self) -> inspect::ProbeStep { match self { WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal), - WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()), WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()), WipProbeStep::RecordImplArgs { impl_args } => { inspect::ProbeStep::RecordImplArgs { impl_args } @@ -278,6 +235,15 @@ impl<'tcx> ProofTreeBuilder> { ProofTreeBuilder { state: Some(Box::new(state.into())) } } + fn opt_nested>>>( + &self, + state: impl FnOnce() -> Option, + ) -> Self { + ProofTreeBuilder { + state: self.state.as_ref().and_then(|_| Some(state()?.into())).map(Box::new), + } + } + fn nested>>>(&self, state: impl FnOnce() -> T) -> Self { ProofTreeBuilder { state: self.state.as_ref().map(|_| Box::new(state().into())) } } @@ -302,22 +268,10 @@ impl<'tcx> ProofTreeBuilder> { } pub fn new_maybe_root( - tcx: TyCtxt<'tcx>, generate_proof_tree: GenerateProofTree, ) -> ProofTreeBuilder> { match generate_proof_tree { - GenerateProofTree::Never => ProofTreeBuilder::new_noop(), - GenerateProofTree::IfEnabled => { - let opts = &tcx.sess.opts.unstable_opts; - match opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() { - DumpSolverProofTree::Always => ProofTreeBuilder::new_root(), - // `OnError` is handled by reevaluating goals in error - // reporting with `GenerateProofTree::Yes`. - DumpSolverProofTree::OnError | DumpSolverProofTree::Never => { - ProofTreeBuilder::new_noop() - } - } - } + GenerateProofTree::No => ProofTreeBuilder::new_noop(), GenerateProofTree::Yes => ProofTreeBuilder::new_root(), } } @@ -340,15 +294,13 @@ impl<'tcx> ProofTreeBuilder> { orig_values: &[ty::GenericArg<'tcx>], kind: solve::GoalEvaluationKind, ) -> ProofTreeBuilder> { - self.nested(|| WipGoalEvaluation { - uncanonicalized_goal: goal, - kind: match kind { - solve::GoalEvaluationKind::Root => { - WipGoalEvaluationKind::Root { orig_values: orig_values.to_vec() } - } - solve::GoalEvaluationKind::Nested => WipGoalEvaluationKind::Nested, - }, - evaluation: None, + self.opt_nested(|| match kind { + solve::GoalEvaluationKind::Root => Some(WipGoalEvaluation { + uncanonicalized_goal: goal, + orig_values: orig_values.to_vec(), + evaluation: None, + }), + solve::GoalEvaluationKind::Nested => None, }) } @@ -359,24 +311,22 @@ impl<'tcx> ProofTreeBuilder> { self.nested(|| WipCanonicalGoalEvaluation { goal, kind: None, - revisions: vec![], + final_revision: None, result: None, }) } - pub fn finalize_evaluation( + pub fn finalize_canonical_goal_evaluation( &mut self, tcx: TyCtxt<'tcx>, - ) -> Option<&'tcx [inspect::GoalEvaluationStep>]> { + ) -> Option<&'tcx inspect::CanonicalGoalEvaluationStep>> { self.as_mut().map(|this| match this { DebugSolver::CanonicalGoalEvaluation(evaluation) => { - let revisions = mem::take(&mut evaluation.revisions) - .into_iter() - .map(WipGoalEvaluationStep::finalize); - let revisions = &*tcx.arena.alloc_from_iter(revisions); - let kind = WipCanonicalGoalEvaluationKind::Interned { revisions }; + let final_revision = mem::take(&mut evaluation.final_revision).unwrap(); + let final_revision = &*tcx.arena.alloc(final_revision.finalize()); + let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision }; assert_eq!(evaluation.kind.replace(kind), None); - revisions + final_revision } _ => unreachable!(), }) @@ -400,7 +350,10 @@ impl<'tcx> ProofTreeBuilder> { } } - pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind>) { + pub fn canonical_goal_evaluation_kind( + &mut self, + kind: WipCanonicalGoalEvaluationKind>, + ) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { @@ -413,17 +366,11 @@ impl<'tcx> ProofTreeBuilder> { pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder>) { if let Some(this) = self.as_mut() { - match (this, *goal_evaluation.state.unwrap()) { - ( - DebugSolver::GoalEvaluationStep(state), - DebugSolver::GoalEvaluation(goal_evaluation), - ) => state - .added_goals_evaluation() - .evaluations - .last_mut() - .unwrap() - .push(goal_evaluation), - (this @ DebugSolver::Root, goal_evaluation) => *this = goal_evaluation, + match this { + DebugSolver::Root => *this = *goal_evaluation.state.unwrap(), + DebugSolver::CanonicalGoalEvaluationStep(_) => { + assert!(goal_evaluation.state.is_none()) + } _ => unreachable!(), } } @@ -434,7 +381,7 @@ impl<'tcx> ProofTreeBuilder> { var_values: CanonicalVarValues<'tcx>, instantiated_goal: QueryInput, ty::Predicate<'tcx>>, ) -> ProofTreeBuilder> { - self.nested(|| WipGoalEvaluationStep { + self.nested(|| WipCanonicalGoalEvaluationStep { var_values: var_values.var_values.to_vec(), instantiated_goal, evaluation: WipProbe { @@ -452,9 +399,9 @@ impl<'tcx> ProofTreeBuilder> { match (this, *goal_evaluation_step.state.unwrap()) { ( DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations), - DebugSolver::GoalEvaluationStep(goal_evaluation_step), + DebugSolver::CanonicalGoalEvaluationStep(goal_evaluation_step), ) => { - canonical_goal_evaluations.revisions.push(goal_evaluation_step); + canonical_goal_evaluations.final_revision = Some(goal_evaluation_step); } _ => unreachable!(), } @@ -464,7 +411,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn add_var_value>>(&mut self, arg: T) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { state.var_values.push(arg.into()); } Some(s) => bug!("tried to add var values to {s:?}"), @@ -474,7 +421,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn enter_probe(&mut self) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let initial_num_var_values = state.var_values.len(); state.current_evaluation_scope().steps.push(WipProbeStep::NestedProbe(WipProbe { initial_num_var_values, @@ -491,7 +438,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn probe_kind(&mut self, probe_kind: inspect::ProbeKind>) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let prev = state.current_evaluation_scope().kind.replace(probe_kind); assert_eq!(prev, None); } @@ -506,7 +453,7 @@ impl<'tcx> ProofTreeBuilder> { ) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let final_state = canonical::make_canonical_state( infcx, &state.var_values, @@ -543,7 +490,7 @@ impl<'tcx> ProofTreeBuilder> { ) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let goal = canonical::make_canonical_state( infcx, &state.var_values, @@ -563,7 +510,7 @@ impl<'tcx> ProofTreeBuilder> { impl_args: ty::GenericArgsRef<'tcx>, ) { match self.as_mut() { - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let impl_args = canonical::make_canonical_state( infcx, &state.var_values, @@ -582,7 +529,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) { match self.as_mut() { - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { state .current_evaluation_scope() .steps @@ -596,7 +543,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn finish_probe(mut self) -> ProofTreeBuilder> { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { assert_ne!(state.probe_depth, 0); let num_var_values = state.current_evaluation_scope().initial_num_var_values; state.var_values.truncate(num_var_values); @@ -608,46 +555,13 @@ impl<'tcx> ProofTreeBuilder> { self } - pub fn start_evaluate_added_goals(&mut self) { - match self.as_mut() { - None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { - state.current_evaluation_scope().steps.push(WipProbeStep::EvaluateGoals( - WipAddedGoalsEvaluation { evaluations: vec![], result: None }, - )); - } - _ => bug!(), - } - } - - pub fn start_evaluate_added_goals_step(&mut self) { - match self.as_mut() { - None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { - state.added_goals_evaluation().evaluations.push(vec![]); - } - _ => bug!(), - } - } - - pub fn evaluate_added_goals_result(&mut self, result: Result) { - match self.as_mut() { - None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { - let prev = state.added_goals_evaluation().result.replace(result); - assert_eq!(prev, None); - } - _ => bug!(), - } - } - pub fn query_result(&mut self, result: QueryResult>) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { assert_eq!(canonical_goal_evaluation.result.replace(result), None); } - DebugSolver::GoalEvaluationStep(evaluation_step) => { + DebugSolver::CanonicalGoalEvaluationStep(evaluation_step) => { assert_eq!( evaluation_step .evaluation diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs index bcd210f789bfe..6be623b6044f0 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs @@ -274,7 +274,8 @@ impl<'tcx> SearchGraph> { last.encountered_overflow = true; } - inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::Overflow); + inspect + .canonical_goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::Overflow); return Self::response_no_constraints(tcx, input, Certainty::overflow(true)); }; @@ -302,8 +303,9 @@ impl<'tcx> SearchGraph> { // We have a nested goal which is already in the provisional cache, use // its result. We do not provide any usage kind as that should have been // already set correctly while computing the cache entry. - inspect - .goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::ProvisionalCacheHit); + inspect.canonical_goal_evaluation_kind( + inspect::WipCanonicalGoalEvaluationKind::ProvisionalCacheHit, + ); Self::tag_cycle_participants(&mut self.stack, HasBeenUsed::empty(), entry.head); return entry.result; } else if let Some(stack_depth) = cache_entry.stack_depth { @@ -314,7 +316,9 @@ impl<'tcx> SearchGraph> { // // Finally we can return either the provisional response or the initial response // in case we're in the first fixpoint iteration for this goal. - inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CycleInStack); + inspect.canonical_goal_evaluation_kind( + inspect::WipCanonicalGoalEvaluationKind::CycleInStack, + ); let is_coinductive_cycle = Self::stack_coinductive_from(tcx, &self.stack, stack_depth); let usage_kind = if is_coinductive_cycle { HasBeenUsed::COINDUCTIVE_CYCLE @@ -371,7 +375,7 @@ impl<'tcx> SearchGraph> { (current_entry, result) }); - let proof_tree = inspect.finalize_evaluation(tcx); + let proof_tree = inspect.finalize_canonical_goal_evaluation(tcx); // We're now done with this goal. In case this goal is involved in a larger cycle // do not remove it from the provisional cache and update its provisional result. @@ -433,9 +437,9 @@ impl<'tcx> SearchGraph> { // the goal. We simply overwrite the existing entry once we're done, // caching the proof tree. if !inspect.is_noop() { - if let Some(revisions) = proof_tree { - let kind = inspect::WipCanonicalGoalEvaluationKind::Interned { revisions }; - inspect.goal_evaluation_kind(kind); + if let Some(final_revision) = proof_tree { + let kind = inspect::WipCanonicalGoalEvaluationKind::Interned { final_revision }; + inspect.canonical_goal_evaluation_kind(kind); } else { return None; } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index e50edfdc656ce..633d488f7be5f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -7,15 +7,11 @@ pub mod suggestions; mod type_err_ctxt_ext; use super::{Obligation, ObligationCause, ObligationCauseCode, PredicateObligation}; -use crate::infer::InferCtxt; -use crate::solve::{GenerateProofTree, InferCtxtEvalExt}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; -use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; -use std::io::Write; use std::ops::ControlFlow; pub use self::infer_ctxt_ext::*; @@ -184,16 +180,3 @@ pub enum DefIdOrName { DefId(DefId), Name(&'static str), } - -pub fn dump_proof_tree<'tcx>(o: &Obligation<'tcx, ty::Predicate<'tcx>>, infcx: &InferCtxt<'tcx>) { - infcx.probe(|_| { - let goal = Goal { predicate: o.predicate, param_env: o.param_env }; - let tree = infcx - .evaluate_root_goal(goal, GenerateProofTree::Yes) - .1 - .expect("proof tree should have been generated"); - let mut lock = std::io::stdout().lock(); - let _ = lock.write_fmt(format_args!("{tree:?}\n")); - let _ = lock.flush(); - }); -} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 494fca0336cc0..46953a61296ac 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -46,7 +46,6 @@ use rustc_middle::ty::{ TypeVisitableExt, Upcast, }; use rustc_middle::{bug, span_bug}; -use rustc_session::config::DumpSolverProofTree; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::sym; @@ -56,8 +55,8 @@ use std::fmt; use std::iter; use super::{ - dump_proof_tree, ArgKind, CandidateSimilarity, FindExprBySpan, FindTypeParam, - GetSafeTransmuteErrorAndReason, HasNumericInferVisitor, ImplCandidate, UnsatisfiedConst, + ArgKind, CandidateSimilarity, FindExprBySpan, FindTypeParam, GetSafeTransmuteErrorAndReason, + HasNumericInferVisitor, ImplCandidate, UnsatisfiedConst, }; pub use rustc_infer::traits::error_reporting::*; @@ -369,13 +368,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { error: &SelectionError<'tcx>, ) -> ErrorGuaranteed { let tcx = self.tcx; - - if tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() - == DumpSolverProofTree::OnError - { - dump_proof_tree(root_obligation, self.infcx); - } - let mut span = obligation.cause.span; let mut err = match *error { @@ -1529,12 +1521,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { #[instrument(skip(self), level = "debug")] fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed { - if self.tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() - == DumpSolverProofTree::OnError - { - dump_proof_tree(&error.root_obligation, self.infcx); - } - match error.code { FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error( error.obligation.clone(), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4a94643d908bf..696b1c1511531 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2539,7 +2539,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&cause, obligation.param_env) - .eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref) + .eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref) .map_err(|e| { debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx())) })?; @@ -2594,7 +2594,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { self.infcx .at(&obligation.cause, obligation.param_env) .eq( - DefineOpaqueTypes::No, + DefineOpaqueTypes::Yes, upcast_principal.map_bound(|trait_ref| { ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) }), @@ -2631,7 +2631,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { nested.extend( self.infcx .at(&obligation.cause, obligation.param_env) - .eq(DefineOpaqueTypes::No, source_projection, target_projection) + .eq(DefineOpaqueTypes::Yes, source_projection, target_projection) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), ); diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 9b8bb210ff424..c77414afc52c7 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -5,7 +5,7 @@ use std::ops::Deref; use crate::inherent::*; use crate::ir_print::IrPrint; -use crate::solve::inspect::GoalEvaluationStep; +use crate::solve::inspect::CanonicalGoalEvaluationStep; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{ AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate, @@ -55,7 +55,11 @@ pub trait Interner: type PredefinedOpaques: Copy + Debug + Hash + Eq; type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable; type ExternalConstraints: Copy + Debug + Hash + Eq; - type GoalEvaluationSteps: Copy + Debug + Hash + Eq + Deref]>; + type CanonicalGoalEvaluationStepRef: Copy + + Debug + + Hash + + Eq + + Deref>; // Kinds of tys type Ty: Ty; diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs index c4f6ee2669bef..0733c730064b0 100644 --- a/compiler/rustc_type_ir/src/solve/inspect.rs +++ b/compiler/rustc_type_ir/src/solve/inspect.rs @@ -1,36 +1,29 @@ //! Data structure used to inspect trait solver behavior. //! //! During trait solving we optionally build "proof trees", the root of -//! which is a [GoalEvaluation] with [GoalEvaluationKind::Root]. These -//! trees are used to improve the debug experience and are also used by -//! the compiler itself to provide necessary context for error messages. +//! which is a [GoalEvaluation]. These trees are used by the compiler +//! to inspect the behavior of the trait solver and to access its internal +//! state, e.g. for diagnostics and when selecting impls during codegen. //! //! Because each nested goal in the solver gets [canonicalized] separately //! and we discard inference progress via "probes", we cannot mechanically //! use proof trees without somehow "lifting up" data local to the current -//! `InferCtxt`. Any data used mechanically is therefore canonicalized and -//! stored as [CanonicalState]. As printing canonicalized data worsens the -//! debugging dumps, we do not simply canonicalize everything. +//! `InferCtxt`. To use the data from evaluation we therefore canonicalize +//! it and store it as a [CanonicalState]. //! -//! This means proof trees contain inference variables and placeholders -//! local to a different `InferCtxt` which must not be used with the -//! current one. +//! Proof trees are only shallow, we do not compute the proof tree for nested +//! goals. Visiting proof trees instead recomputes nested goals in the parents +//! inference context when necessary. //! //! [canonicalized]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html -mod format; - -use std::fmt::{Debug, Write}; -use std::hash::Hash; - -use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; - -use self::format::ProofTreeFormatter; use crate::solve::{ - CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, NoSolution, QueryInput, - QueryResult, + CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult, }; use crate::{Canonical, CanonicalVarValues, Interner}; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; +use std::fmt::Debug; +use std::hash::Hash; /// Some `data` together with information about how they relate to the input /// of the canonical query. @@ -55,23 +48,15 @@ pub struct State { pub type CanonicalState = Canonical>; -/// When evaluating the root goals we also store the -/// original values for the `CanonicalVarValues` of the -/// canonicalized goal. We use this to map any [CanonicalState] -/// from the local `InferCtxt` of the solver query to -/// the `InferCtxt` of the caller. -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] -pub enum GoalEvaluationKind { - Root { orig_values: Vec }, - Nested, -} - +/// When evaluating a goal we also store the original values +/// for the `CanonicalVarValues` of the canonicalized goal. +/// We use this to map any [CanonicalState] from the local `InferCtxt` +/// of the solver query to the `InferCtxt` of the caller. #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] pub struct GoalEvaluation { pub uncanonicalized_goal: Goal, - pub kind: GoalEvaluationKind, + pub orig_values: Vec, pub evaluation: CanonicalGoalEvaluation, } @@ -89,24 +74,12 @@ pub enum CanonicalGoalEvaluationKind { Overflow, CycleInStack, ProvisionalCacheHit, - Evaluation { revisions: I::GoalEvaluationSteps }, -} -impl Debug for GoalEvaluation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ProofTreeFormatter::new(f).format_goal_evaluation(self) - } + Evaluation { final_revision: I::CanonicalGoalEvaluationStepRef }, } #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] -pub struct AddedGoalsEvaluation { - pub evaluations: Vec>>, - pub result: Result, -} - -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] -pub struct GoalEvaluationStep { +pub struct CanonicalGoalEvaluationStep { pub instantiated_goal: QueryInput, /// The actual evaluation of the goal, always `ProbeKind::Root`. @@ -117,7 +90,7 @@ pub struct GoalEvaluationStep { /// corresponds to a `EvalCtxt::probe(_X)` call or the root evaluation /// of a goal. #[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] +#[derivative(Debug(bound = ""), PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] pub struct Probe { /// What happened inside of this probe in chronological order. pub steps: Vec>, @@ -125,23 +98,15 @@ pub struct Probe { pub final_state: CanonicalState, } -impl Debug for Probe { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ProofTreeFormatter::new(f).format_probe(self) - } -} - #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] pub enum ProbeStep { /// We added a goal to the `EvalCtxt` which will get proven /// the next time `EvalCtxt::try_evaluate_added_goals` is called. AddGoal(GoalSource, CanonicalState>), - /// The inside of a `EvalCtxt::try_evaluate_added_goals` call. - EvaluateGoals(AddedGoalsEvaluation), /// A call to `probe` while proving the current goal. This is /// used whenever there are multiple candidates to prove the - /// current goalby . + /// current goal. NestedProbe(Probe), /// A trait goal was satisfied by an impl candidate. RecordImplArgs { impl_args: CanonicalState }, diff --git a/compiler/rustc_type_ir/src/solve/inspect/format.rs b/compiler/rustc_type_ir/src/solve/inspect/format.rs deleted file mode 100644 index 44ade04cf98ca..0000000000000 --- a/compiler/rustc_type_ir/src/solve/inspect/format.rs +++ /dev/null @@ -1,173 +0,0 @@ -use std::marker::PhantomData; - -use super::*; - -pub(super) struct ProofTreeFormatter<'a, 'b, I> { - f: &'a mut (dyn Write + 'b), - _interner: PhantomData, -} - -enum IndentorState { - StartWithNewline, - OnNewline, - Inline, -} - -/// A formatter which adds 4 spaces of indentation to its input before -/// passing it on to its nested formatter. -/// -/// We can use this for arbitrary levels of indentation by nesting it. -struct Indentor<'a, 'b> { - f: &'a mut (dyn Write + 'b), - state: IndentorState, -} - -impl Write for Indentor<'_, '_> { - fn write_str(&mut self, s: &str) -> std::fmt::Result { - for line in s.split_inclusive('\n') { - match self.state { - IndentorState::StartWithNewline => self.f.write_str("\n ")?, - IndentorState::OnNewline => self.f.write_str(" ")?, - IndentorState::Inline => {} - } - self.state = - if line.ends_with('\n') { IndentorState::OnNewline } else { IndentorState::Inline }; - self.f.write_str(line)?; - } - - Ok(()) - } -} - -impl<'a, 'b, I: Interner> ProofTreeFormatter<'a, 'b, I> { - pub(super) fn new(f: &'a mut (dyn Write + 'b)) -> Self { - ProofTreeFormatter { f, _interner: PhantomData } - } - - fn nested(&mut self, func: F) -> std::fmt::Result - where - F: FnOnce(&mut ProofTreeFormatter<'_, '_, I>) -> std::fmt::Result, - { - write!(self.f, " {{")?; - func(&mut ProofTreeFormatter { - f: &mut Indentor { f: self.f, state: IndentorState::StartWithNewline }, - _interner: PhantomData, - })?; - writeln!(self.f, "}}") - } - - pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation) -> std::fmt::Result { - let goal_text = match eval.kind { - GoalEvaluationKind::Root { orig_values: _ } => "ROOT GOAL", - GoalEvaluationKind::Nested => "GOAL", - }; - write!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?; - self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation)) - } - - pub(super) fn format_canonical_goal_evaluation( - &mut self, - eval: &CanonicalGoalEvaluation, - ) -> std::fmt::Result { - writeln!(self.f, "GOAL: {:?}", eval.goal)?; - - match &eval.kind { - CanonicalGoalEvaluationKind::Overflow => { - writeln!(self.f, "OVERFLOW: {:?}", eval.result) - } - CanonicalGoalEvaluationKind::CycleInStack => { - writeln!(self.f, "CYCLE IN STACK: {:?}", eval.result) - } - CanonicalGoalEvaluationKind::ProvisionalCacheHit => { - writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", eval.result) - } - CanonicalGoalEvaluationKind::Evaluation { revisions } => { - for (n, step) in revisions.iter().enumerate() { - write!(self.f, "REVISION {n}")?; - self.nested(|this| this.format_evaluation_step(step))?; - } - writeln!(self.f, "RESULT: {:?}", eval.result) - } - } - } - - pub(super) fn format_evaluation_step( - &mut self, - evaluation_step: &GoalEvaluationStep, - ) -> std::fmt::Result { - writeln!(self.f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?; - self.format_probe(&evaluation_step.evaluation) - } - - pub(super) fn format_probe(&mut self, probe: &Probe) -> std::fmt::Result { - match &probe.kind { - ProbeKind::Root { result } => { - write!(self.f, "ROOT RESULT: {result:?}") - } - ProbeKind::TryNormalizeNonRigid { result } => { - write!(self.f, "TRY NORMALIZE NON-RIGID: {result:?}") - } - ProbeKind::NormalizedSelfTyAssembly => { - write!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:") - } - ProbeKind::UnsizeAssembly => { - write!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:") - } - ProbeKind::UpcastProjectionCompatibility => { - write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") - } - ProbeKind::OpaqueTypeStorageLookup { result } => { - write!(self.f, "PROBING FOR AN EXISTING OPAQUE: {result:?}") - } - 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| { - for step in &probe.steps { - match step { - ProbeStep::AddGoal(source, goal) => { - let source = match source { - GoalSource::Misc => "misc", - GoalSource::ImplWhereBound => "impl where-bound", - GoalSource::InstantiateHigherRanked => "higher-ranked goal", - }; - writeln!(this.f, "ADDED GOAL ({source}): {goal:?}")? - } - ProbeStep::EvaluateGoals(eval) => this.format_added_goals_evaluation(eval)?, - ProbeStep::NestedProbe(probe) => this.format_probe(probe)?, - ProbeStep::MakeCanonicalResponse { shallow_certainty } => { - writeln!(this.f, "EVALUATE GOALS AND MAKE RESPONSE: {shallow_certainty:?}")? - } - ProbeStep::RecordImplArgs { impl_args } => { - writeln!(this.f, "RECORDED IMPL ARGS: {impl_args:?}")? - } - } - } - Ok(()) - }) - } - - pub(super) fn format_added_goals_evaluation( - &mut self, - added_goals_evaluation: &AddedGoalsEvaluation, - ) -> std::fmt::Result { - writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", added_goals_evaluation.result)?; - - for (n, iterations) in added_goals_evaluation.evaluations.iter().enumerate() { - write!(self.f, "ITERATION {n}")?; - self.nested(|this| { - for goal_evaluation in iterations { - this.format_goal_evaluation(goal_evaluation)?; - } - Ok(()) - })?; - } - - Ok(()) - } -} diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index 80b9e0cf15214..f7fe8eb1c7fd5 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -116,6 +116,9 @@ pub struct ReentrantLockGuard<'a, T: ?Sized + 'a> { #[unstable(feature = "reentrant_lock", issue = "121440")] impl !Send for ReentrantLockGuard<'_, T> {} +#[unstable(feature = "reentrant_lock", issue = "121440")] +unsafe impl Sync for ReentrantLockGuard<'_, T> {} + #[unstable(feature = "reentrant_lock", issue = "121440")] impl ReentrantLock { /// Creates a new re-entrant lock in an unlocked state ready for use. diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs index 2f908e3d0e956..eb3a57c212b4a 100644 --- a/library/std/src/sys/pal/unix/alloc.rs +++ b/library/std/src/sys/pal/unix/alloc.rs @@ -59,10 +59,9 @@ unsafe impl GlobalAlloc for System { } cfg_if::cfg_if! { - // We use posix_memalign wherever possible, but not all targets have that function. + // We use posix_memalign wherever possible, but some targets have very incomplete POSIX coverage + // so we need a fallback for those. if #[cfg(any( - target_os = "redox", - target_os = "espidf", target_os = "horizon", target_os = "vita", ))] { @@ -74,12 +73,11 @@ cfg_if::cfg_if! { #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let mut out = ptr::null_mut(); - // We prefer posix_memalign over aligned_malloc since with aligned_malloc, - // implementations are making almost arbitrary choices for which alignments are - // "supported", making it hard to use. For instance, some implementations require the - // size to be a multiple of the alignment (wasi emmalloc), while others require the - // alignment to be at least the pointer size (Illumos, macOS) -- which may or may not be - // standards-compliant, but that does not help us. + // We prefer posix_memalign over aligned_alloc since it is more widely available, and + // since with aligned_alloc, implementations are making almost arbitrary choices for + // which alignments are "supported", making it hard to use. For instance, some + // implementations require the size to be a multiple of the alignment (wasi emmalloc), + // while others require the alignment to be at least the pointer size (Illumos, macOS). // posix_memalign only has one, clear requirement: that the alignment be a multiple of // `sizeof(void*)`. Since these are all powers of 2, we can just use max. let align = layout.align().max(crate::mem::size_of::()); diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index c9b9c54e3d49c..6948670565662 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -121,10 +121,8 @@ fn x86_all() { println!("avx512bw: {:?}", is_x86_feature_detected!("avx512bw")); println!("avx512cd: {:?}", is_x86_feature_detected!("avx512cd")); println!("avx512dq: {:?}", is_x86_feature_detected!("avx512dq")); - println!("avx512er: {:?}", is_x86_feature_detected!("avx512er")); println!("avx512f: {:?}", is_x86_feature_detected!("avx512f")); println!("avx512ifma: {:?}", is_x86_feature_detected!("avx512ifma")); - println!("avx512pf: {:?}", is_x86_feature_detected!("avx512pf")); println!("avx512vbmi2: {:?}", is_x86_feature_detected!("avx512vbmi2")); println!("avx512vbmi: {:?}", is_x86_feature_detected!("avx512vbmi")); println!("avx512vl: {:?}", is_x86_feature_detected!("avx512vl")); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 19119a073c5fa..d13dc9d1d177a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -360,7 +360,7 @@ pub enum RustfmtState { LazyEvaluated, } -#[derive(Debug, Default, Clone, Copy, PartialEq)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum LlvmLibunwind { #[default] No, @@ -381,7 +381,7 @@ impl FromStr for LlvmLibunwind { } } -#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum SplitDebuginfo { Packed, Unpacked, @@ -542,7 +542,7 @@ impl PartialEq<&str> for TargetSelection { } /// Per-target configuration stored in the global configuration structure. -#[derive(Default, Clone)] +#[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct Target { /// Some(path to llvm-config) if using an external LLVM. pub llvm_config: Option, @@ -644,7 +644,20 @@ impl Merge for TomlConfig { do_merge(&mut self.llvm, llvm, replace); do_merge(&mut self.rust, rust, replace); do_merge(&mut self.dist, dist, replace); - assert!(target.is_none(), "merging target-specific config is not currently supported"); + + match (self.target.as_mut(), target) { + (_, None) => {} + (None, Some(target)) => self.target = Some(target), + (Some(original_target), Some(new_target)) => { + for (triple, new) in new_target { + if let Some(original) = original_target.get_mut(&triple) { + original.merge(new, replace); + } else { + original_target.insert(triple, new); + } + } + } + } } } @@ -899,7 +912,7 @@ define_config! { } } -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] #[serde(untagged)] pub enum StringOrBool { String(String), diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 59e16b6542728..c4073910623a4 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -1,5 +1,7 @@ use super::{flags::Flags, ChangeIdWrapper, Config}; use crate::core::build_steps::clippy::get_clippy_rules_in_order; +use crate::core::config::Target; +use crate::core::config::TargetSelection; use crate::core::config::{LldMode, TomlConfig}; use clap::CommandFactory; @@ -124,6 +126,10 @@ fn override_toml() { "--set=build.gdb=\"bar\"".to_owned(), "--set=build.tools=[\"cargo\"]".to_owned(), "--set=llvm.build-config={\"foo\" = \"bar\"}".to_owned(), + "--set=target.x86_64-unknown-linux-gnu.runner=bar".to_owned(), + "--set=target.x86_64-unknown-linux-gnu.rpath=false".to_owned(), + "--set=target.aarch64-unknown-linux-gnu.sanitizers=false".to_owned(), + "--set=target.aarch64-apple-darwin.runner=apple".to_owned(), ], |&_| { toml::from_str( @@ -140,6 +146,17 @@ tools = [] [llvm] download-ci-llvm = false build-config = {} + +[target.aarch64-unknown-linux-gnu] +sanitizers = true +rpath = true +runner = "aarch64-runner" + +[target.x86_64-unknown-linux-gnu] +sanitizers = true +rpath = true +runner = "x86_64-runner" + "#, ) .unwrap() @@ -163,6 +180,30 @@ build-config = {} [("foo".to_string(), "bar".to_string())].into_iter().collect(), "setting dictionary value" ); + + let x86_64 = TargetSelection::from_user("x86_64-unknown-linux-gnu"); + let x86_64_values = Target { + sanitizers: Some(true), + rpath: Some(false), + runner: Some("bar".into()), + ..Default::default() + }; + let aarch64 = TargetSelection::from_user("aarch64-unknown-linux-gnu"); + let aarch64_values = Target { + sanitizers: Some(false), + rpath: Some(true), + runner: Some("aarch64-runner".into()), + ..Default::default() + }; + let darwin = TargetSelection::from_user("aarch64-apple-darwin"); + let darwin_values = Target { runner: Some("apple".into()), ..Default::default() }; + assert_eq!( + config.target_config, + [(x86_64, x86_64_values), (aarch64, aarch64_values), (darwin, darwin_values)] + .into_iter() + .collect(), + "setting dictionary value" + ); } #[test] diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr index 834ae00a8d85b..ffb02eccc77dc 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr @@ -6,8 +6,12 @@ LL | drop(origin); | | | argument has type `::Output` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_copy_types)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(origin); +LL + let _ = origin; + | warning: 1 warning emitted diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr index 0f944a18ed58b..e6ae8183e77dc 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr @@ -6,8 +6,12 @@ LL | drop(origin); | | | argument has type `::Output` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_copy_types)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(origin); +LL + let _ = origin; + | warning: 1 warning emitted diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 8c1bf5a11607d..b3d0046fc1788 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, and `bmi2` and 188 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, and `bulk-memory` and 186 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index c13446bb9f89b..0c50ec1abba99 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/codegen/mono-impossible-drop.rs b/tests/ui/codegen/mono-impossible-drop.rs new file mode 100644 index 0000000000000..dec013cfe54b3 --- /dev/null +++ b/tests/ui/codegen/mono-impossible-drop.rs @@ -0,0 +1,18 @@ +//@ compile-flags: -Clink-dead-code=on --crate-type=lib +//@ build-pass + +#![feature(trivial_bounds)] +#![allow(trivial_bounds)] + +// Make sure we don't monomorphize the drop impl for `Baz`, since it has predicates +// that don't hold under a reveal-all param env. + +trait Foo { + type Assoc; +} + +struct Bar; + +struct Baz(::Assoc) +where + Bar: Foo; diff --git a/tests/ui/impl-trait/equality.rs b/tests/ui/impl-trait/equality.rs index 828b5aac896be..952f81f19784c 100644 --- a/tests/ui/impl-trait/equality.rs +++ b/tests/ui/impl-trait/equality.rs @@ -22,7 +22,7 @@ fn sum_to(n: u32) -> impl Foo { 0 } else { n + sum_to(n - 1) - //~^ ERROR cannot add `impl Foo` to `u32` + //~^ ERROR cannot satisfy `>::Output == i32` } } @@ -32,12 +32,15 @@ trait Leak: Sized { } impl Leak for T { default type T = (); - default fn leak(self) -> Self::T { panic!() } + default fn leak(self) -> Self::T { + panic!() + } } impl Leak for i32 { type T = i32; - fn leak(self) -> i32 { self } + fn leak(self) -> i32 { + self + } } -fn main() { -} +fn main() {} diff --git a/tests/ui/impl-trait/equality.stderr b/tests/ui/impl-trait/equality.stderr index 69f4cbbbf4294..c9ba1a5ba32d1 100644 --- a/tests/ui/impl-trait/equality.stderr +++ b/tests/ui/impl-trait/equality.stderr @@ -22,20 +22,13 @@ help: change the type of the numeric literal from `u32` to `i32` LL | 0_i32 | ~~~ -error[E0277]: cannot add `impl Foo` to `u32` +error[E0284]: type annotations needed: cannot satisfy `>::Output == i32` --> $DIR/equality.rs:24:11 | LL | n + sum_to(n - 1) - | ^ no implementation for `u32 + impl Foo` - | - = help: the trait `Add` is not implemented for `u32` - = help: the following other types implement trait `Add`: - <&'a u32 as Add> - <&u32 as Add<&u32>> - > - + | ^ cannot satisfy `>::Output == i32` error: aborting due to 2 previous errors; 1 warning emitted -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0284, E0308. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index 1f9a2a5e9d600..f7c708a1dfae8 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -46,19 +46,23 @@ error[E0277]: the trait bound `impl Into: Into` is not satisfie --> $DIR/nested_impl_trait.rs:6:46 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Into`, which is required by `impl Into: Into` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into` | - = help: the trait `Into` is implemented for `T` - = note: required for `impl Into` to implement `Into` +help: consider further restricting this bound + | +LL | fn bad_in_ret_position(x: impl Into + std::fmt::Debug) -> impl Into { x } + | +++++++++++++++++ error[E0277]: the trait bound `impl Into: Into` is not satisfied --> $DIR/nested_impl_trait.rs:19:34 | LL | fn bad(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Into`, which is required by `impl Into: Into` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into` + | +help: consider further restricting this bound | - = help: the trait `Into` is implemented for `T` - = note: required for `impl Into` to implement `Into` +LL | fn bad(x: impl Into + std::fmt::Debug) -> impl Into { x } + | +++++++++++++++++ error: aborting due to 7 previous errors diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs index aab10be2de27a..7874a21f3aec5 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs @@ -11,7 +11,7 @@ impl PartialEq<(Bar, i32)> for Bar { } fn foo() -> Foo { - //~^ ERROR can't compare `Bar` with `(Foo, i32)` + //~^ ERROR overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>` Bar } diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr index bc810c0f88f3d..2d4707f8a2799 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr @@ -1,15 +1,9 @@ -error[E0277]: can't compare `Bar` with `(Foo, i32)` +error[E0275]: overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>` --> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13 | LL | fn foo() -> Foo { - | ^^^ no implementation for `Bar == (Foo, i32)` -LL | -LL | Bar - | --- return type was inferred to be `Bar` here - | - = help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar` - = help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar` + | ^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/impl-trait/unsize_adt.rs b/tests/ui/impl-trait/unsize_adt.rs new file mode 100644 index 0000000000000..fce5094bd404c --- /dev/null +++ b/tests/ui/impl-trait/unsize_adt.rs @@ -0,0 +1,14 @@ +//! Test that we do not allow unsizing `Foo<[Opaque; N]>` to `Foo<[Concrete]>`. + +struct Foo(T); + +fn hello() -> Foo<[impl Sized; 2]> { + if false { + let x = hello(); + let _: &Foo<[i32]> = &x; + //~^ ERROR: mismatched types + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/unsize_adt.stderr b/tests/ui/impl-trait/unsize_adt.stderr new file mode 100644 index 0000000000000..2b93b4a571b1b --- /dev/null +++ b/tests/ui/impl-trait/unsize_adt.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/unsize_adt.rs:8:30 + | +LL | fn hello() -> Foo<[impl Sized; 2]> { + | ---------- the found opaque type +... +LL | let _: &Foo<[i32]> = &x; + | ----------- ^^ expected `&Foo<[i32]>`, found `&Foo<[impl Sized; 2]>` + | | + | expected due to this + | + = note: expected reference `&Foo<[i32]>` + found reference `&Foo<[impl Sized; 2]>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/unsize_slice.rs b/tests/ui/impl-trait/unsize_slice.rs new file mode 100644 index 0000000000000..ec0f162656400 --- /dev/null +++ b/tests/ui/impl-trait/unsize_slice.rs @@ -0,0 +1,12 @@ +//! Test that we do not allow unsizing `[Opaque; N]` to `[Concrete]`. + +fn hello() -> [impl Sized; 2] { + if false { + let x = hello(); + let _: &[i32] = &x; + //~^ ERROR: mismatched types + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/unsize_slice.stderr b/tests/ui/impl-trait/unsize_slice.stderr new file mode 100644 index 0000000000000..6a7fdb46163b9 --- /dev/null +++ b/tests/ui/impl-trait/unsize_slice.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/unsize_slice.rs:6:25 + | +LL | fn hello() -> [impl Sized; 2] { + | ---------- the found opaque type +... +LL | let _: &[i32] = &x; + | ------ ^^ expected `&[i32]`, found `&[impl Sized; 2]` + | | + | expected due to this + | + = note: expected reference `&[i32]` + found reference `&[impl Sized; 2]` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/unsize_tuple.rs b/tests/ui/impl-trait/unsize_tuple.rs new file mode 100644 index 0000000000000..630b8fd430f1a --- /dev/null +++ b/tests/ui/impl-trait/unsize_tuple.rs @@ -0,0 +1,14 @@ +//! Test that we do not allow unsizing `([Opaque; N],)` to `([Concrete],)`. + +#![feature(unsized_tuple_coercion)] + +fn hello() -> ([impl Sized; 2],) { + if false { + let x = hello(); + let _: &([i32],) = &x; + //~^ ERROR: mismatched types + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/unsize_tuple.stderr b/tests/ui/impl-trait/unsize_tuple.stderr new file mode 100644 index 0000000000000..8d3cf15887c08 --- /dev/null +++ b/tests/ui/impl-trait/unsize_tuple.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/unsize_tuple.rs:8:28 + | +LL | fn hello() -> ([impl Sized; 2],) { + | ---------- the found opaque type +... +LL | let _: &([i32],) = &x; + | --------- ^^ expected `&([i32],)`, found `&([impl Sized; 2],)` + | | + | expected due to this + | + = note: expected reference `&([i32],)` + found reference `&([impl Sized; 2],)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs new file mode 100644 index 0000000000000..12c984c932acf --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs @@ -0,0 +1,14 @@ +//@ check-fail + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + let z = 2; + match y { + 0 => drop(y), //~ ERROR calls to `std::mem::drop` + 1 => drop(z), //~ ERROR calls to `std::mem::drop` + 2 => drop(3), //~ ERROR calls to `std::mem::drop` + _ => {}, + } +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr new file mode 100644 index 0000000000000..6c73e5ea90b47 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr @@ -0,0 +1,37 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:9:14 + | +LL | 0 => drop(y), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result +note: the lint level is defined here + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:3:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:10:14 + | +LL | 1 => drop(z), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:11:14 + | +LL | 2 => drop(3), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.fixed b/tests/ui/lint/dropping_copy_types-issue-125189.fixed new file mode 100644 index 0000000000000..2dfd68d4cc16a --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.fixed @@ -0,0 +1,10 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + let _ = 3.2; //~ ERROR calls to `std::mem::drop` + let _ = y; //~ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.rs b/tests/ui/lint/dropping_copy_types-issue-125189.rs new file mode 100644 index 0000000000000..1f42efabba9ff --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.rs @@ -0,0 +1,10 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + drop(3.2); //~ ERROR calls to `std::mem::drop` + drop(y); //~ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.stderr b/tests/ui/lint/dropping_copy_types-issue-125189.stderr new file mode 100644 index 0000000000000..ba3e36f5b6ec4 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.stderr @@ -0,0 +1,35 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189.rs:8:5 + | +LL | drop(3.2); + | ^^^^^---^ + | | + | argument has type `f64` + | +note: the lint level is defined here + --> $DIR/dropping_copy_types-issue-125189.rs:4:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(3.2); +LL + let _ = 3.2; + | + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189.rs:9:5 + | +LL | drop(y); + | ^^^^^-^ + | | + | argument has type `i32` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(y); +LL + let _ = y; + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/dropping_copy_types.stderr b/tests/ui/lint/dropping_copy_types.stderr index b6291aa5ed634..bdeb0c290fe93 100644 --- a/tests/ui/lint/dropping_copy_types.stderr +++ b/tests/ui/lint/dropping_copy_types.stderr @@ -6,12 +6,16 @@ LL | drop(s1); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/dropping_copy_types.rs:3:9 | LL | #![warn(dropping_copy_types)] | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s1); +LL + let _ = s1; + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:35:5 @@ -21,7 +25,11 @@ LL | drop(s2); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s2); +LL + let _ = s2; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:36:5 @@ -42,7 +50,11 @@ LL | drop(s4); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s4); +LL + let _ = s4; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:38:5 @@ -82,7 +94,11 @@ LL | drop(println_and(13)); | | | argument has type `i32` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(println_and(13)); +LL + let _ = println_and(13); + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:74:14 diff --git a/tests/ui/sync/reentrantlockguard-sync.rs b/tests/ui/sync/reentrantlockguard-sync.rs new file mode 100644 index 0000000000000..84d5b1834a882 --- /dev/null +++ b/tests/ui/sync/reentrantlockguard-sync.rs @@ -0,0 +1,15 @@ +#![feature(reentrant_lock)] +use std::sync::ReentrantLock; +use std::cell::Cell; + +// ReentrantLockGuard> must not be Sync, that would be unsound. + +fn test_sync(_t: T) {} + +fn main() +{ + let m = ReentrantLock::new(Cell::new(0i32)); + let guard = m.lock(); + test_sync(guard); + //~^ ERROR `Cell` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/sync/reentrantlockguard-sync.stderr b/tests/ui/sync/reentrantlockguard-sync.stderr new file mode 100644 index 0000000000000..ed2e3e2f1124a --- /dev/null +++ b/tests/ui/sync/reentrantlockguard-sync.stderr @@ -0,0 +1,20 @@ +error[E0277]: `Cell` cannot be shared between threads safely + --> $DIR/reentrantlockguard-sync.rs:13:15 + | +LL | test_sync(guard); + | --------- ^^^^^ `Cell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `Cell`, which is required by `ReentrantLockGuard<'_, Cell>: Sync` + = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead + = note: required for `ReentrantLockGuard<'_, Cell>` to implement `Sync` +note: required by a bound in `test_sync` + --> $DIR/reentrantlockguard-sync.rs:7:17 + | +LL | fn test_sync(_t: T) {} + | ^^^^ required by this bound in `test_sync` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/typeck/index-of-projection.rs b/tests/ui/traits/next-solver/typeck/index-of-projection.rs new file mode 100644 index 0000000000000..5023be0bb1482 --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/index-of-projection.rs @@ -0,0 +1,13 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Fixes a regression in `rustc_attr` where we weren't normalizing the +// output type of a index operator performing a `Ty::builtin_index` call, +// leading to an ICE. + +fn main() { + let mut vec = [1, 2, 3]; + let x = || { + let [..] = &vec[..]; + }; +} diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs new file mode 100644 index 0000000000000..5820e49a4e52d --- /dev/null +++ b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs @@ -0,0 +1,28 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@[next] failure-status: 101 +//@[next] known-bug: unknown +//@[next] normalize-stderr-test "note: .*\n\n" -> "" +//@[next] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> "" +//@[next] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +//@[next] normalize-stderr-test "delayed at .*" -> "" +//@[next] rustc-env:RUST_BACKTRACE=0 +//@ check-pass + +#![feature(trait_upcasting)] + +trait Super { + type Assoc; +} + +trait Sub: Super {} + +impl Super for T { + type Assoc = i32; +} + +fn illegal(x: &dyn Sub) -> &dyn Super { + x +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs index f40c48f0d125f..01759ec7a93c6 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs @@ -11,6 +11,10 @@ fn test_correct(x: &dyn Foo<'static>) { let _ = x as &dyn Bar<'static, 'static>; } +fn test_correct2<'a>(x: &dyn Foo<'a>) { + let _ = x as &dyn Bar<'_, '_>; +} + fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { let _ = x as &dyn Bar<'static, 'a>; // Error //~^ ERROR lifetime may not live long enough diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr index 8d506e5807ece..ccced5875778d 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:15:13 + --> $DIR/type-checking-test-4.rs:19:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -7,7 +7,7 @@ LL | let _ = x as &dyn Bar<'static, 'a>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:20:13 + --> $DIR/type-checking-test-4.rs:24:13 | LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -15,7 +15,7 @@ LL | let _ = x as &dyn Bar<'a, 'static>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:26:5 + --> $DIR/type-checking-test-4.rs:30:5 | LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -24,7 +24,7 @@ LL | y.get_b() // ERROR | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:31:5 + --> $DIR/type-checking-test-4.rs:35:5 | LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -32,7 +32,7 @@ LL | <_ as Bar>::get_b(x) // ERROR | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:36:5 + --> $DIR/type-checking-test-4.rs:40:5 | LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -40,7 +40,7 @@ LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:44:5 + --> $DIR/type-checking-test-4.rs:48:5 | LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs new file mode 100644 index 0000000000000..a3a1ce29465b1 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs @@ -0,0 +1,22 @@ +#![feature(trait_upcasting, type_alias_impl_trait)] + +//@ check-pass + +type Tait = impl Sized; + +trait Foo<'a>: Bar<'a, 'a, Tait> {} +trait Bar<'a, 'b, T> {} + +fn test_correct(x: &dyn Foo<'static>) { + let _ = x as &dyn Bar<'static, 'static, Tait>; +} + +fn test_correct2<'a>(x: &dyn Foo<'a>) { + let _ = x as &dyn Bar<'_, '_, Tait>; +} + +fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) { + let _ = x as &dyn Bar<'_, '_, ()>; +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr deleted file mode 100644 index a259abb28ae3e..0000000000000 --- a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/upcast-defining-opaque.rs:21:5 - | -LL | type Foo = impl Sized; - | ---------- the found opaque type -LL | -LL | fn upcast(x: &dyn Sub) -> &dyn Super { - | ----------------------- expected `&dyn Super` because of return type -LL | x - | ^ expected trait `Super`, found trait `Sub` - | - = note: expected reference `&dyn Super` - found reference `&dyn Sub` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs index cb1501a94a2ae..07f1549e177fb 100644 --- a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs +++ b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs @@ -1,7 +1,7 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] check-pass +//@check-pass #![feature(trait_upcasting, type_alias_impl_trait)] @@ -18,7 +18,7 @@ impl Super for T { type Foo = impl Sized; fn upcast(x: &dyn Sub) -> &dyn Super { - x //[current]~ mismatched types + x } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs new file mode 100644 index 0000000000000..2a246900106cb --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs @@ -0,0 +1,27 @@ +//! Check that projections will constrain opaque types while looking for +//! matching impls. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@check-pass + +#![feature(type_alias_impl_trait)] + +struct Foo; + +type Bar = impl Sized; + +trait Trait { + type Assoc: Default; +} + +impl Trait<()> for Foo { + type Assoc = u32; +} + +fn bop(_: Bar) { + let x = >::Assoc::default(); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr new file mode 100644 index 0000000000000..0d6eac4216bae --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr @@ -0,0 +1,19 @@ +error[E0283]: type annotations needed: cannot satisfy `Foo: Trait` + --> $DIR/constrain_in_projection2.rs:27:14 + | +LL | let x = >::Assoc::default(); + | ^^^ help: use the fully qualified path to an implementation: `::Assoc` + | +note: multiple `impl`s satisfying `Foo: Trait` found + --> $DIR/constrain_in_projection2.rs:18:1 + | +LL | impl Trait<()> for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Trait for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr new file mode 100644 index 0000000000000..0d6eac4216bae --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr @@ -0,0 +1,19 @@ +error[E0283]: type annotations needed: cannot satisfy `Foo: Trait` + --> $DIR/constrain_in_projection2.rs:27:14 + | +LL | let x = >::Assoc::default(); + | ^^^ help: use the fully qualified path to an implementation: `::Assoc` + | +note: multiple `impl`s satisfying `Foo: Trait` found + --> $DIR/constrain_in_projection2.rs:18:1 + | +LL | impl Trait<()> for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Trait for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs new file mode 100644 index 0000000000000..0066131f0155f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs @@ -0,0 +1,31 @@ +//! Check that projections will constrain opaque types while looking for +//! matching impls and error if ambiguous. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(type_alias_impl_trait)] + +struct Foo; + +type Bar = impl Sized; + +trait Trait { + type Assoc: Default; +} + +impl Trait<()> for Foo { + type Assoc = u32; +} + +impl Trait for Foo { + type Assoc = u32; +} + +fn bop(_: Bar) { + let x = >::Assoc::default(); + //~^ ERROR: cannot satisfy `Foo: Trait` +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr similarity index 90% rename from tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr rename to tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr index 461da20f37b67..a7ff097e8bf38 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` - --> $DIR/issue-84660-unsoundness.rs:23:1 + --> $DIR/issue-84660-unsoundness.rs:28:1 | LL | impl Trait for Out { | ------------------------------------ first implementation here diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr new file mode 100644 index 0000000000000..607f0b062abd7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr @@ -0,0 +1,23 @@ +error[E0284]: type annotations needed: cannot satisfy `>::Out == ()` + --> $DIR/issue-84660-unsoundness.rs:22:37 + | +LL | fn convert(_i: In) -> Self::Out { + | _____________________________________^ +LL | | +LL | | unreachable!(); +LL | | } + | |_____^ cannot satisfy `>::Out == ()` + +error[E0119]: conflicting implementations of trait `Trait` + --> $DIR/issue-84660-unsoundness.rs:28:1 + | +LL | impl Trait for Out { + | ------------------------------------ first implementation here +... +LL | impl Trait<(), In> for Out { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0119, E0284. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs index 48d4b0c96ff0a..99a5d36066b08 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs @@ -1,6 +1,10 @@ // Another example from issue #84660, this time weaponized as a safe transmute: an opaque type in an // impl header being accepted was used to create unsoundness. +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + #![feature(type_alias_impl_trait)] trait Foo {} @@ -16,11 +20,13 @@ trait Trait { impl Trait for Out { type Out = Out; fn convert(_i: In) -> Self::Out { + //[next]~^ ERROR: type annotations needed unreachable!(); } } -impl Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait` +impl Trait<(), In> for Out { + //~^ ERROR conflicting implementations of trait `Trait` type Out = In; fn convert(i: In) -> Self::Out { i diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs index 82248971692ce..70495c44706a7 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs @@ -1,18 +1,21 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@check-pass + use std::fmt::Debug; type FooX = impl Debug; -trait Foo { } +trait Foo {} -impl Foo<()> for () { } +impl Foo<()> for () {} fn foo() -> impl Foo { - //~^ ERROR: the trait bound `(): Foo` is not satisfied - // FIXME(type-alias-impl-trait): We could probably make this work. () } -fn main() { } +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr new file mode 100644 index 0000000000000..c7b7af152ab32 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed: cannot satisfy `(): Foo` + --> $DIR/nested-tait-inference2.rs:17:13 + | +LL | fn foo() -> impl Foo { + | ^^^^^^^^^^^^^^ + | +note: multiple `impl`s satisfying `(): Foo` found + --> $DIR/nested-tait-inference2.rs:14:1 + | +LL | impl Foo<()> for () {} + | ^^^^^^^^^^^^^^^^^^^ +LL | impl Foo for () {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr new file mode 100644 index 0000000000000..9647d9e376eb4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr @@ -0,0 +1,9 @@ +error[E0284]: type annotations needed: cannot satisfy `impl Foo == ()` + --> $DIR/nested-tait-inference2.rs:19:5 + | +LL | () + | ^^ cannot satisfy `impl Foo == ()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs index 0d7f5bad25f11..fe2f76e552ad7 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -1,6 +1,10 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + use std::fmt::Debug; type FooX = impl Debug; @@ -11,8 +15,9 @@ impl Foo<()> for () {} impl Foo for () {} fn foo() -> impl Foo { - //~^ ERROR: the trait bound `(): Foo` is not satisfied + //[current]~^ ERROR: cannot satisfy `(): Foo` () + //[next]~^ ERROR: cannot satisfy `impl Foo == ()` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr deleted file mode 100644 index 241342b05096b..0000000000000 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/nested-tait-inference2.rs:13:13 - | -LL | fn foo() -> impl Foo { - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` -LL | -LL | () - | -- return type was inferred to be `()` here - | - = help: the following other types implement trait `Foo`: - <() as Foo<()>> - <() as Foo> - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr index a40dac06a01c3..eff29303bf18e 100644 --- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr +++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr @@ -22,21 +22,17 @@ note: previous use here LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) } | ^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types +error: concrete type differs from previous defining opaque type use --> $DIR/normalize-hidden-types.rs:43:25 | -LL | type Opaque = impl Sized; - | ---------- the expected opaque type -... LL | let _: Opaque = dyn_hoops::(0); - | ------ ^^^^^^^^^^^^^^^^^^ expected opaque type, found `*const dyn FnOnce(())` - | | - | expected due to this - | - = note: expected opaque type `typeck::Opaque` - found raw pointer `*const (dyn FnOnce(()) + 'static)` - = help: consider constraining the associated type `::Gat<'_>` to `()` or calling a method that returns `::Gat<'_>` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + | ^^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(::Gat<'a>)` + | +note: previous use here + --> $DIR/normalize-hidden-types.rs:44:9 + | +LL | None + | ^^^^ error: concrete type differs from previous defining opaque type use --> $DIR/normalize-hidden-types.rs:52:25 @@ -52,4 +48,3 @@ LL | None error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr deleted file mode 100644 index 3ae3590ca7fe3..0000000000000 --- a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0277]: can't compare `i32` with `Foo` - --> $DIR/self-referential-2.rs:10:13 - | -LL | fn bar() -> Bar { - | ^^^ no implementation for `i32 == Foo` -LL | 42_i32 - | ------ return type was inferred to be `i32` here - | - = help: the trait `PartialEq` is not implemented for `i32` - = help: the trait `PartialEq` is implemented for `i32` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.rs b/tests/ui/type-alias-impl-trait/self-referential-2.rs index f96364ccfcddf..f4102f2e2cb71 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-2.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-2.rs @@ -1,14 +1,14 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass #![feature(type_alias_impl_trait)] type Foo = impl std::fmt::Debug; type Bar = impl PartialEq; fn bar() -> Bar { - 42_i32 //[current]~^ ERROR can't compare `i32` with `Foo` + 42_i32 } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs index b33051da2d779..3b015ab322aca 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-3.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs @@ -5,7 +5,7 @@ type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { - //~^ ERROR can't compare `&i32` with `Bar<'a, 'b>` + //~^ ERROR overflow normalizing the type alias `Bar<'a, 'b>` i } diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.stderr b/tests/ui/type-alias-impl-trait/self-referential-3.stderr index 32eac622e5181..caa9f9691dda5 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-3.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-3.stderr @@ -1,15 +1,11 @@ -error[E0277]: can't compare `&i32` with `Bar<'a, 'b>` +error[E0275]: overflow normalizing the type alias `Bar<'a, 'b>` --> $DIR/self-referential-3.rs:7:31 | LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { - | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>` -LL | -LL | i - | - return type was inferred to be `&i32` here + | ^^^^^^^^^^^ | - = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the trait `PartialEq` is implemented for `i32` + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0275`.