diff --git a/.mailmap b/.mailmap index 9166494632a00..219f21c05096a 100644 --- a/.mailmap +++ b/.mailmap @@ -687,8 +687,9 @@ Tomas Koutsky Tomasz Miąsko Torsten Weber Torsten Weber -Trevor Gross -Trevor Gross +Trevor Gross +Trevor Gross +Trevor Gross Trevor Spiteri Tshepang Mbambo Ty Overby diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 687776386e36e..5691b1c9eb399 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -970,17 +970,19 @@ fn get_flavor_from_path(path: &Path) -> CrateFlavor { } } -/// A function to fetch about all macros inside a proc-macro crate. +/// A function to fetch all macros inside a proc-macro crate. /// /// Used by rust-analyzer-proc-macro-srv. pub fn get_proc_macros( - target: &Target, path: &Path, metadata_loader: &dyn MetadataLoader, cfg_version: &'static str, ) -> IoResult> { + let host_tuple = TargetTuple::from_tuple(config::host_tuple()); + let (host, _) = Target::search(&host_tuple, Path::new(""), false).unwrap(); + let metadata = - get_metadata_section(target, CrateFlavor::Dylib, path, metadata_loader, cfg_version, None) + get_metadata_section(&host, CrateFlavor::Dylib, path, metadata_loader, cfg_version, None) .map_err(|err| io::Error::other(err.to_string()))?; let stable_crate_id = metadata.get_root().stable_crate_id(); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index ec855b4debd04..06d882a309489 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -20,8 +20,8 @@ use tracing::{debug, instrument}; use crate::error_reporting::TypeErrCtxt; use crate::error_reporting::infer::need_type_info::TypeAnnotationNeeded; use crate::error_reporting::traits::{FindExprBySpan, to_pretty_impl_header}; -use crate::traits::ObligationCtxt; use crate::traits::query::evaluate_obligation::InferCtxtExt; +use crate::traits::{FulfillmentError, ObligationCtxt}; #[derive(Debug)] pub enum CandidateSource { @@ -174,10 +174,43 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( } impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { + /// The term of an ambiguous obligation's predicate that gets blamed for the + /// missing type annotation: the first one still containing inference variables. + /// + /// Besides `maybe_report_ambiguity` pointing its diagnostics at this term, + /// `report_fulfillment_errors` merges the ambiguity errors whose blamed terms + /// share an inference variable into a single diagnostic. + pub(super) fn ambiguity_term(&self, predicate: ty::Predicate<'tcx>) -> Option> { + match predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => data + .trait_ref + .args + .iter() + .filter_map(ty::GenericArg::as_term) + .find(|term| term.has_non_region_infer()), + ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => data + .projection_term + .args + .iter() + .filter_map(ty::GenericArg::as_term) + .chain([data.term]) + .find(|term| term.has_non_region_infer()), + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => Some(term), + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => { + data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer()) + } + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) => Some(ct.into()), + ty::PredicateKind::Subtype(data) => Some(data.a.into()), + ty::PredicateKind::NormalizesTo(data) if data.term.is_infer() => Some(data.term), + _ => None, + } + } + #[instrument(skip(self), level = "debug")] pub(super) fn maybe_report_ambiguity( &self, obligation: &PredicateObligation<'tcx>, + related: &[&FulfillmentError<'tcx>], ) -> ErrorGuaranteed { // Unable to successfully determine, probably means // insufficient type information, but could mean @@ -255,12 +288,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Pick the first generic parameter that still contains inference variables as the one // we're going to emit an error for. If there are none (see above), fall back to // a more general error. - let term = data - .trait_ref - .args - .iter() - .filter_map(ty::GenericArg::as_term) - .find(|s| s.has_non_region_infer()); + let term = self.ambiguity_term(predicate); let mut err = if let Some(term) = term { let candidates: Vec<_> = self @@ -306,34 +334,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .with_long_ty_path(long_ty_path) }; - let mut ambiguities = compute_applicable_impls_for_diagnostics( - self.infcx, - &obligation.with(self.tcx, trait_pred), - false, - ); - let has_non_region_infer = trait_pred - .skip_binder() - .trait_ref - .args - .types() - .any(|t| !t.is_ty_or_numeric_infer()); - // It doesn't make sense to talk about applicable impls if there are more than a - // handful of them. If there are a lot of them, but only a few of them have no type - // params, we only show those, as they are more likely to be useful/intended. - if ambiguities.len() > 5 { - let infcx = self.infcx; - if !ambiguities.iter().all(|option| match option { - CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0, - CandidateSource::ParamEnv(_) => true, - }) { - // If not all are blanket impls, we filter blanked impls out. - ambiguities.retain(|option| match option { - CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0, - CandidateSource::ParamEnv(_) => true, - }); - } - } - if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer { + if let Some(ambiguities) = self.applicable_impls_to_mention(obligation, trait_pred) + { if let Some(e) = self.tainted_by_errors() && term.is_none() { @@ -590,13 +592,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // other `Foo` impls are incoherent. return guar; } - let term = data - .projection_term - .args - .iter() - .filter_map(ty::GenericArg::as_term) - .chain([data.term]) - .find(|g| g.has_non_region_infer()); + let term = self.ambiguity_term(predicate); let predicate = self.tcx.short_string(predicate, &mut long_ty_path); if let Some(term) = term { self.emit_inference_failure_err( @@ -621,16 +617,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => { + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(_)) => { if let Err(e) = predicate.error_reported() { return e; } if let Some(e) = self.tainted_by_errors() { return e; } - let term = - data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer()); - if let Some(term) = term { + if let Some(term) = self.ambiguity_term(predicate) { self.emit_inference_failure_err( obligation.cause.body_def_id, span, @@ -713,10 +707,119 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .with_long_ty_path(long_ty_path) } }; + + // The related obligations are ambiguous because of the same inference variable, + // so they belong to this diagnostic: annotating the variable has to satisfy all + // of them at once. Mention their requirements, except for bookkeeping predicates + // (`WellFormed`, sizedness, ...) whose mention wouldn't be actionable. + let mut mentioned = vec![predicate]; + let mut mentioned_strs: Vec = vec![]; + for &error in related { + let related_pred = self.resolve_vars_if_possible(error.obligation.predicate); + if mentioned.contains(&related_pred) { + continue; + } + let note = match related_pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) + if !matches!( + self.tcx.as_lang_item(data.def_id()), + Some(LangItem::Sized | LangItem::MetaSized | LangItem::PointeeSized) + ) => + { + let clause = related_pred.kind().rebind(data); + if let ty::Infer(_) = clause.self_ty().skip_binder().kind() { + let tr = self.tcx.short_string( + clause.print_modifiers_and_trait_path(), + &mut err.long_ty_path(), + ); + format!("the type must also implement `{tr}`") + } else { + let pred = self.tcx.short_string(related_pred, &mut err.long_ty_path()); + let note = format!("cannot satisfy `{pred}`"); + // The self type is known, so the `impl`s that could have applied to it are + // few and worth pointing at, like the blamed bound does. When it is still + // an inference variable the list is every `impl` of the trait, which is + // why the branch above only names the trait. + // + // `tainted_by_errors` is checked because `annotate_source_of_ambiguity` + // downgrades the whole diagnostic once an error was already emitted. + if !mentioned_strs.contains(¬e) + && self.tainted_by_errors().is_none() + && let Some(ambiguities) = + self.applicable_impls_to_mention(&error.obligation, clause) + { + self.annotate_source_of_ambiguity(&mut err, &ambiguities, related_pred); + mentioned_strs.push(note); + mentioned.push(related_pred); + continue; + } + note + } + } + ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { + let pred = self.tcx.short_string(related_pred, &mut err.long_ty_path()); + format!("cannot satisfy `{pred}`") + } + _ => { + mentioned.push(related_pred); + continue; + } + }; + // Two predicates can print identically (e.g. `From` and `From` both show as + // `From<_>`); only emit each unique note string once. + if !mentioned_strs.contains(¬e) { + err.note(note.clone()); + mentioned_strs.push(note); + } + mentioned.push(related_pred); + } + self.note_obligation_cause(&mut err, obligation); + // The merged errors are not reported on their own anymore, so the bounds they came from + // have to be explained here too. Causes shared with the blamed obligation are already + // described by the call above. + for &error in related { + if error.obligation.cause.code() != obligation.cause.code() { + self.note_obligation_cause(&mut err, &error.obligation); + } + } err.emit() } + /// The `impl`s and `where` clauses that could have satisfied `trait_pred`, when listing them + /// is likely to help. `None` means the caller should describe the bound some other way. + fn applicable_impls_to_mention( + &self, + obligation: &PredicateObligation<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) -> Option> { + let mut ambiguities = compute_applicable_impls_for_diagnostics( + self.infcx, + &obligation.with(self.tcx, trait_pred), + false, + ); + let has_non_region_infer = + trait_pred.skip_binder().trait_ref.args.types().any(|t| !t.is_ty_or_numeric_infer()); + // It doesn't make sense to talk about applicable impls if there are more than a + // handful of them. If there are a lot of them, but only a few of them have no type + // params, we only show those, as they are more likely to be useful/intended. + if ambiguities.len() > 5 { + let infcx = self.infcx; + if !ambiguities.iter().all(|option| match option { + CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0, + CandidateSource::ParamEnv(_) => true, + }) { + // If not all are blanket impls, we filter blanked impls out. + ambiguities.retain(|option| match option { + CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0, + CandidateSource::ParamEnv(_) => true, + }); + } + } + (ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer) + .then_some(ambiguities) + } + fn annotate_source_of_ambiguity( &self, err: &mut Diag<'_>, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 76b4900367bde..8bf5814b9fe13 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -11,6 +11,7 @@ use rustc_crate_store::{ExternCrate, ExternCrateSource}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err}; +use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, AmbigArg}; @@ -21,6 +22,7 @@ use rustc_infer::traits::{ }; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _}; +use rustc_next_trait_solver::solve::TyOrConstInferVar; use rustc_span::{DesugaringKind, ErrorGuaranteed, ExpnKind, Span}; use thin_vec::ThinVec; use tracing::{info, instrument}; @@ -250,12 +252,99 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } + // Ambiguity errors blaming the same inference variable describe a single problem: + // annotating that one variable has to satisfy all of them at once. Reporting them + // separately loses all but the first, as the rest get canceled as duplicates once + // the `infcx` is tainted (see `maybe_report_ambiguity`), hiding their requirements + // from the user. Instead, report the first one (the sort above placed the most + // informative obligation first) and mention the requirements of the others in it. + // + // Type variables that are only related through a pending `Coerce` or `Subtype` + // obligation still concern the same annotation, so compare their sub-unification + // roots, like `need_type_info` does when looking for the annotation source. + let ambiguity_infer_var = |error: &FulfillmentError<'tcx>| match error.code { + FulfillmentErrorCode::Ambiguity { overflow: None } => self + .ambiguity_term(self.resolve_vars_if_possible(error.obligation.predicate)) + .and_then(|term| { + ty::GenericArg::from(term) + .walk() + .find_map(TyOrConstInferVar::maybe_from_generic_arg::>) + }) + .map(|var| match var { + TyOrConstInferVar::Ty(vid) => { + TyOrConstInferVar::Ty(self.sub_unification_table_root_var(vid)) + } + other => other, + }), + _ => None, + }; + let infer_vars: Vec<_> = errors.iter().map(ambiguity_infer_var).collect(); + let mut reported = None; + let mut merged = vec![None; errors.len()]; + let mut reported_as_primary = vec![false; errors.len()]; for from_expansion in [false, true] { - for (error, suppressed) in iter::zip(&errors, &is_suppressed) { + for (index, (error, suppressed)) in iter::zip(&errors, &is_suppressed).enumerate() { if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion { if !error.references_error() { - let guar = self.report_fulfillment_error(error); + let guar = if let Some(guar) = merged[index] { + guar + } else { + let group: Vec = match infer_vars[index] { + Some(var) => (0..errors.len()) + .filter(|&other| { + other != index && infer_vars[other] == Some(var) + }) + .collect(), + None => vec![], + }; + // Only merge errors that a note on this diagnostic can fully + // represent. An error blaming a different expression labels that + // expression and suggests how to annotate it, and one whose + // predicate we can't phrase as a note (e.g. const evaluatability) + // says nothing here, so both keep their own error. + let merges = |other: usize| { + errors[other].obligation.cause.span == error.obligation.cause.span + && match errors[other].obligation.predicate.kind().skip_binder() + { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { + !matches!( + self.tcx.as_lang_item(data.def_id()), + Some( + LangItem::Sized + | LangItem::MetaSized + | LangItem::PointeeSized + ) + ) + } + ty::PredicateKind::Clause(ty::ClauseKind::Projection( + _, + )) => true, + _ => false, + } + }; + let related: Vec<_> = group + .iter() + .filter(|&&other| { + // Exclude already-reported primaries: they were their own + // canonical error and adding them as notes here would + // produce duplicate information. + merges(other) + && !is_suppressed[other] + && !errors[other].references_error() + && !reported_as_primary[other] + }) + .map(|&other| &errors[other]) + .collect(); + let guar = self.report_fulfillment_error(error, &related); + for &other in &group { + if merges(other) { + merged[other] = Some(guar); + } + } + reported_as_primary[index] = true; + guar + }; self.infcx.set_tainted_by_errors(guar); reported = Some(guar); // We want to ignore desugarings here: spans are equivalent even @@ -286,7 +375,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed { + fn report_fulfillment_error( + &self, + error: &FulfillmentError<'tcx>, + related: &[&FulfillmentError<'tcx>], + ) -> ErrorGuaranteed { let mut error = FulfillmentError { obligation: error.obligation.clone(), code: error.code.clone(), @@ -311,7 +404,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.report_projection_error(&error.obligation, e) } FulfillmentErrorCode::Ambiguity { overflow: None } => { - self.maybe_report_ambiguity(&error.obligation) + self.maybe_report_ambiguity(&error.obligation, related) } FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) } => { self.report_overflow_no_abort(error.obligation.clone(), suggest_increasing_limit) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index e3653bd393c85..5e1ac67e7b50b 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -31,8 +31,8 @@ use rustc_macros::TypeVisitable; use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ - self, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, + self, BottomUpFolder, Clause, GenericArgs, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, }; use rustc_span::Span; @@ -267,13 +267,65 @@ fn set_projection_term_to_non_rigid<'tcx>( }) } +enum ReplaceRegions { + Yes, + No, +} + +fn replace_infer_and_non_rigid_alias_with_error<'tcx, T>( + infcx: &InferCtxt<'tcx>, + value: T, + guar: ErrorGuaranteed, + replace_regions: ReplaceRegions, +) -> T +where + T: TypeFoldable>, +{ + let tcx = infcx.tcx; + value.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| { + let ty = infcx.shallow_resolve(ty); + match ty.kind() { + ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => { + Ty::new_error(tcx, guar) + } + ty::Alias(ty::IsRigid::No, _) if tcx.next_trait_solver_globally() => { + Ty::new_error(tcx, guar) + } + _ => ty, + } + }, + lt_op: |lt| match replace_regions { + // We can't resolve regions using lexical resolution here since + // that's private. It probably doesn't matter since we already + // got more severe error. + ReplaceRegions::Yes => match lt.kind() { + ty::ReVar(_) => ty::Region::new_error(tcx, guar), + _ => lt, + }, + ReplaceRegions::No => lt, + }, + ct_op: |ct| { + let ct = infcx.shallow_resolve_const(ct); + match ct.kind() { + ty::ConstKind::Infer(ty::InferConst::Var(_)) => ty::Const::new_error(tcx, guar), + ty::ConstKind::Alias(ty::IsRigid::No, _) if tcx.next_trait_solver_globally() => { + ty::Const::new_error(tcx, guar) + } + _ => ct, + } + }, + }) +} + #[instrument(level = "debug", skip(tcx, elaborated_env))] fn do_normalize_clauses<'tcx>( tcx: TyCtxt<'tcx>, cause: ObligationCause<'tcx>, elaborated_env: ty::ParamEnv<'tcx>, clauses: Vec>, -) -> Result>, ErrorGuaranteed> { +) -> Vec> { // FIXME. We should really... do something with these region // obligations. But this call just continues the older // behavior (i.e., doesn't cause any new bugs), and it would @@ -287,7 +339,6 @@ fn do_normalize_clauses<'tcx>( // by wfcheck anyway, so I'm not sure we have to check // them here too, and we will remove this function when // we move over to lazy normalization *anyway*. - let span = cause.span; let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); // FIXME: `elaborated_env` is not really rigid. We do this to be @@ -322,16 +373,16 @@ fn do_normalize_clauses<'tcx>( }; let errors = ocx.evaluate_obligations_error_on_ambiguity(); - if let TraitErrors::HasErrors(errors) = errors { - let reported = infcx.err_ctxt().report_fulfillment_errors(errors); - return Err(reported); - } + let clauses = if let TraitErrors::HasErrors(errors) = errors { + debug!("do_normalize_clauses: failed to normalize clauses"); + let guar = infcx.err_ctxt().report_fulfillment_errors(errors); + replace_infer_and_non_rigid_alias_with_error(&infcx, clauses, guar, ReplaceRegions::No) + } else { + clauses + }; debug!("do_normalize_clauses: normalized clauses = {:?}", clauses); - // We can use the `elaborated_env` here; the region code only - // cares about declarations like `'a: 'b`. - // // FIXME: It's very weird that we ignore region obligations but apparently // still need to use `resolve_regions` as we need the resolved regions in // the normalized clauses. @@ -342,21 +393,32 @@ fn do_normalize_clauses<'tcx>( // for `compare_method_clause_entailment`. We should remove this once we have proper // support for implied bounds on binders. // - // This is required by trait-system-refactor-initiative#166. The new solver encounters + // This ignoring is required by trait-system-refactor-initiative#166. The new solver encounters // this more frequently as we entirely ignore outlives clauses with the old solver. - let _errors = infcx.resolve_regions(cause.body_def_id, elaborated_env, []); - match infcx.fully_resolve(clauses) { - Ok(clauses) => Ok(clauses), + // + // FIXME: We should avoid interning clauses both here and at the + // caller sites. We should also avoid cloning if possible. + let normalized_env = ty::ParamEnv::new(tcx.mk_clauses(&clauses)); + let _errors = infcx.resolve_regions(cause.body_def_id, normalized_env, []); + match infcx.fully_resolve(clauses.clone()) { + Ok(clauses) => clauses, Err(fixup_err) => { - // If we encounter a fixup error, it means that some type - // variable wound up unconstrained. That can happen for - // ill-formed impls, so we delay a bug here instead of - // immediately ICEing and let type checking report the + // The first folder only replaces infers from normalization failure. We might not have + // normalization failure and have unconstrained ty/const vars from ill-formed impls. + // See `tests/ui/traits/normalize/self-referential-param-env-normalization.rs`. + // + // We delay a bug here instead of immediately ICEing and let type checking report the // actual user-facing errors. - Err(tcx.dcx().span_delayed_bug( - span, + let guar = tcx.dcx().span_delayed_bug( + cause.span, format!("inference variables in normalized parameter environment: {fixup_err}"), - )) + ); + + // This is slightly wrong as we replace opaques with errors. + // + // We still need to replace regions because `fully_resolve` eagerly returns `Err` if + // it encounters unconstrained ty/const var. Thus region vars might not get replaced. + replace_infer_and_non_rigid_alias_with_error(&infcx, clauses, guar, ReplaceRegions::Yes) } } } @@ -491,13 +553,7 @@ pub fn normalize_param_env_or_error<'tcx>( "normalize_param_env_or_error: clauses=(non-outlives={:?}, outlives={:?})", clauses, outlives_clauses ); - let Ok(non_outlives_clauses) = - do_normalize_clauses(tcx, cause.clone(), elaborated_env, clauses) - else { - // An unnormalized env is better than nothing. - debug!("normalize_param_env_or_error: errored resolving non-outlives clauses"); - return elaborated_env; - }; + let non_outlives_clauses = do_normalize_clauses(tcx, cause.clone(), elaborated_env, clauses); debug!("normalize_param_env_or_error: non-outlives clauses={:?}", non_outlives_clauses); @@ -506,12 +562,7 @@ pub fn normalize_param_env_or_error<'tcx>( // clauses here anyway. Keeping them here anyway because it seems safer. let outlives_env = non_outlives_clauses.iter().chain(&outlives_clauses).cloned(); let outlives_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(outlives_env)); - let Ok(outlives_clauses) = do_normalize_clauses(tcx, cause, outlives_env, outlives_clauses) - else { - // An unnormalized env is better than nothing. - debug!("normalize_param_env_or_error: errored resolving outlives clauses"); - return elaborated_env; - }; + let outlives_clauses = do_normalize_clauses(tcx, cause, outlives_env, outlives_clauses); debug!("normalize_param_env_or_error: outlives clauses={:?}", outlives_clauses); let mut clauses = non_outlives_clauses; diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index aa250c04388e3..ddeb95f27ac2c 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -1012,9 +1012,10 @@ pub enum ComputeGoalFastPathOutcome { TriviallyStalled { stalled_on: GoalStalledOn }, } -/// Helper for `InferCtxt::ty_or_const_infer_var_changed` (see comment on that), currently -/// used only for `traits::fulfill`'s list of `stalled_on` inference variables. -#[derive(Copy, Clone, Debug)] +/// Helper for `InferCtxt::ty_or_const_infer_var_changed` (see comment on that), used +/// for `traits::fulfill`'s list of `stalled_on` inference variables and for merging +/// ambiguity errors caused by the same inference variable during error reporting. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum TyOrConstInferVar { /// Equivalent to `ty::Infer(ty::TyVar(_))`. Ty(TyVid), diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 328e9b47966c9..6269c9fcf9136 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1873,6 +1873,214 @@ where if f(&v2) < f(&v1) { [v2, v1] } else { [v1, v2] } } +/// Calls `mac` on lists of arguments from size `0` to `1 + count($y)`. +macro impl_for_tuples_up_to($mac:ident! { $($x:ident, $($y:ident,)*)? }) { + $(impl_for_tuples_up_to! { + $mac! { $($y,)* } + })? + $mac! { $($x, $($y,)*)? } +} + +/// Calls each `mac` on lists of arguments from size zero to twelve. +macro impl_tuples($($mac:ident,)+) { + $(impl_for_tuples_up_to! { $mac! { x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, } })+ +} + +/// Implementation detail for [`smallest`] and [`largest`]. +/// Marker indicating that `Self` is a tuple where all members are of the same type. +#[diagnostic::on_unimplemented(message = "`{Self}` is not a homogeneous tuple")] +#[unstable(feature = "cmp_splat_internals", issue = "160728")] +#[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] +const trait HomogeneousTuple: crate::marker::Tuple { + /// The type of each item in this tuple. + type Item; +} + +/// Implements [`HomogeneousTuple`] for a provided tuple. +macro impl_homogeneous_tuple($($($x:ident,)+)?) { + $( + #[unstable(feature = "cmp_splat_internals", issue = "160728")] + #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] + const impl HomogeneousTuple for ($(${ignore($x)}T,)+) { + type Item = T; + } + )? +} + +impl_tuples! { + impl_homogeneous_tuple, +} + +/// Compares and returns the minimum of the provided values. +/// +/// Returns the first argument if the comparison determines them to be equal. +/// +/// Internally uses [`Ord::min`]. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_splat)] +/// use std::cmp; +/// +/// assert_eq!(cmp::smallest(1), 1); +/// assert_eq!(cmp::smallest(1, 2), 1); +/// assert_eq!(cmp::smallest(3, 2, 1), 1); +/// assert_eq!(cmp::smallest(1, 2, 3, 4), 1); +/// ``` +/// ``` +/// #![feature(cmp_splat)] +/// use std::cmp::{self, Ordering}; +/// +/// #[derive(Eq)] +/// struct Equal(&'static str); +/// +/// impl PartialEq for Equal { +/// fn eq(&self, other: &Self) -> bool { true } +/// } +/// impl PartialOrd for Equal { +/// fn partial_cmp(&self, other: &Self) -> Option { Some(Ordering::Equal) } +/// } +/// impl Ord for Equal { +/// fn cmp(&self, other: &Self) -> Ordering { Ordering::Equal } +/// } +/// +/// assert_eq!(cmp::smallest(Equal("v1"), Equal("v2")).0, "v1"); +/// ``` +/// +/// # Stability +/// +/// This function is added in its current form as an experiment in variadic functions. +/// In a future iteration of the feature, this function may be removed in favour of +/// making [`min`] itself variadic instead. +#[inline] +#[must_use] +#[unstable(feature = "cmp_splat", issue = "160728")] +#[rustc_const_unstable(feature = "cmp_splat", issue = "160728")] +#[expect(private_bounds, reason = "`SmallestArgs` is an internal implementation detail")] +#[cfg(not(test))] // FIXME: splat interacts poorly with the double linking of `core` in tests +pub const fn smallest( + #[rustc_splat] args: impl [const] SmallestArgs, +) -> T { + SmallestArgs::smallest(args) +} + +/// Implementation detail for [`smallest`]. +#[diagnostic::on_unimplemented(message = "`{Self}` is not a valid set of arguments for `smallest`")] +#[unstable(feature = "cmp_splat_internals", issue = "160728")] +#[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] +const trait SmallestArgs: HomogeneousTuple { + /// Reduces all elements of a homogeneous tuple to its smallest value. + fn smallest(self) -> Self::Item; +} + +/// Implements [`SmallestArgs`] for a provided tuple if applicable. +macro impl_smallest_args($($x:ident, $($($y:ident,)+)?)?) { + $( + #[unstable(feature = "cmp_splat_internals", issue = "160728")] + #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] + const impl SmallestArgs for (T, $($(${ignore($y)}T,)+)?) + $(where T: [const] Destruct + [const] Ord, $(${ignore($y)})+)? + { + #[inline] + fn smallest(self) -> Self::Item { + let ($x, $($($y,)+)?) = self; + $($(let $x = $x.min($y);)+)? + $x + } + } + )? +} + +impl_tuples! { + impl_smallest_args, +} + +/// Compares and returns the maximum of the provided values. +/// +/// Returns the last argument if the comparison determines them to be equal. +/// +/// Internally uses [`Ord::max`]. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_splat)] +/// use std::cmp; +/// +/// assert_eq!(cmp::largest(1), 1); +/// assert_eq!(cmp::largest(1, 2), 2); +/// assert_eq!(cmp::largest(3, 2, 1), 3); +/// assert_eq!(cmp::largest(1, 2, 3, 4), 4); +/// ``` +/// ``` +/// #![feature(cmp_splat)] +/// use std::cmp::{self, Ordering}; +/// +/// #[derive(Eq)] +/// struct Equal(&'static str); +/// +/// impl PartialEq for Equal { +/// fn eq(&self, other: &Self) -> bool { true } +/// } +/// impl PartialOrd for Equal { +/// fn partial_cmp(&self, other: &Self) -> Option { Some(Ordering::Equal) } +/// } +/// impl Ord for Equal { +/// fn cmp(&self, other: &Self) -> Ordering { Ordering::Equal } +/// } +/// +/// assert_eq!(cmp::largest(Equal("v1"), Equal("v2")).0, "v2"); +/// ``` +/// +/// # Stability +/// +/// This function is added in its current form as an experiment in variadic functions. +/// In a future iteration of the feature, this function may be removed in favour of +/// making [`max`] itself variadic instead. +#[inline] +#[must_use] +#[unstable(feature = "cmp_splat", issue = "160728")] +#[rustc_const_unstable(feature = "cmp_splat", issue = "160728")] +#[expect(private_bounds, reason = "`LargestArgs` is an internal implementation detail")] +#[cfg(not(test))] // FIXME: splat interacts poorly with the double linking of `core` in tests +pub const fn largest( + #[rustc_splat] args: impl [const] LargestArgs, +) -> T { + LargestArgs::largest(args) +} + +/// Implementation detail for [`largest`]. +#[diagnostic::on_unimplemented(message = "`{Self}` is not a valid set of arguments for `largest`")] +#[unstable(feature = "cmp_splat_internals", issue = "160728")] +#[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] +const trait LargestArgs: HomogeneousTuple { + /// Reduces all elements of a homogeneous tuple to its largest value. + fn largest(self) -> Self::Item; +} + +/// Implements [`LargestArgs`] for a provided tuple if applicable. +macro impl_largest_args($($x:ident, $($($y:ident,)+)?)?) { + $( + #[unstable(feature = "cmp_splat_internals", issue = "160728")] + #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] + const impl LargestArgs for (T, $($(${ignore($y)}T,)+)?) + $(where T: [const] Destruct + [const] Ord, $(${ignore($y)})+)? + { + #[inline] + fn largest(self) -> Self::Item { + let ($x, $($($y,)+)?) = self; + $($(let $x = $x.max($y);)+)? + $x + } + } + )? +} + +impl_tuples! { + impl_largest_args, +} + // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types mod impls { use crate::cmp::Ordering::{self, Equal, Greater, Less}; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 8a592fce7dfcd..8c85e6d1c0c5e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -155,6 +155,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(simd_ffi)] +#![feature(splat)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] #![feature(strict_provenance_lints)] diff --git a/library/coretests/tests/cmp.rs b/library/coretests/tests/cmp.rs index e6af3575293d6..c739f3e290378 100644 --- a/library/coretests/tests/cmp.rs +++ b/library/coretests/tests/cmp.rs @@ -280,3 +280,12 @@ mod const_cmp { const _: () = assert!(S(0) < S(1)); const _: () = assert!(S(1) > S(0)); } + +mod const_splat { + use super::*; + + const _: () = assert!(cmp::smallest(1, 2, 3, 4) == 1); + const _: () = assert!(cmp::smallest(4, 3, 2, 1) == 1); + const _: () = assert!(cmp::largest(1, 2, 3, 4) == 4); + const _: () = assert!(cmp::largest(4, 3, 2, 1) == 4); +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 35327264ccd77..1f629f01f38dd 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -15,6 +15,7 @@ #![feature(char_internals)] #![feature(clone_to_uninit)] #![feature(cmp_minmax)] +#![feature(cmp_splat)] #![feature(const_array)] #![feature(const_bool)] #![feature(const_cell_traits)] diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 6f6c76d23a454..e3b550b603359 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -24,7 +24,8 @@ use crate::core::builder::{ }; use crate::core::config::{Subcommand, TargetSelection}; use crate::utils::build_stamp::{self, BuildStamp}; -use crate::{Compiler, Mode, exit}; +use crate::utils::helpers; +use crate::{Compiler, Mode}; /// Disable the most spammy clippy lints const IGNORED_RULES_FOR_STD_AND_RUSTC: &[&str] = &[ @@ -543,7 +544,7 @@ impl CommandLineStep for CI { fn run(self, builder: &Builder<'_>) -> Self::Output { if builder.top_stage != 2 { eprintln!("ERROR: `x clippy ci` should always be executed with --stage 2"); - exit!(1); + helpers::exit_process(1); } // We want to check in-tree source using in-tree clippy. However, if we naively did diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index fd8bf473ca921..6b659206fbca5 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -34,11 +34,11 @@ use crate::utils::build_stamp; use crate::utils::build_stamp::BuildStamp; use crate::utils::exec::command; use crate::utils::helpers::{ - exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, + self, exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, }; use crate::{ CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode, - debug, exit, trace, + debug, trace, }; /// Build a standard library for the given `target` using the given `build_compiler`. @@ -2044,7 +2044,7 @@ impl Step for Sysroot { sysroot_lib_rustlib_src_rust.display(), ); } - exit!(1); + helpers::exit_process(1); } } @@ -2062,7 +2062,7 @@ impl Step for Sysroot { builder.src.display(), e, ); - exit!(1); + helpers::exit_process(1); } } @@ -2741,7 +2741,7 @@ pub fn run_cargo( }); if !ok { - crate::exit!(1); + helpers::exit_process(1); } if builder.config.dry_run() { diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index ee74820da0999..d4dc9c2de53e6 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -152,14 +152,14 @@ pub fn format( if build.kind == Kind::Format && build.top_stage != 0 { eprintln!("ERROR: `x fmt` only supports stage 0."); eprintln!("HELP: Use `x run rustfmt` to run in-tree rustfmt."); - crate::exit!(1); + helpers::exit_process(1); } if !paths.is_empty() { eprintln!( "fmt error: path arguments are no longer accepted; use `--all` to format everything" ); - crate::exit!(1); + helpers::exit_process(1); }; if build.config.dry_run() { return; @@ -193,7 +193,7 @@ pub fn format( // explicit whitelisted entries and traversal of unmentioned files, but for now just // forbid such entries. eprintln!("fmt error: `!`-prefixed entries are not supported in rustfmt.toml, sorry"); - crate::exit!(1); + helpers::exit_process(1); } else { override_builder.add(&format!("!{ignore}")).expect(&ignore); } @@ -362,7 +362,7 @@ pub fn format( let result = thread.join().unwrap(); if result.is_err() { - crate::exit!(1); + helpers::exit_process(1); } // Update `build/.rustfmt-stamp`, allowing this code to ignore files which have not been changed diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 67615353b1d9f..739f0d6c1cf02 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -26,7 +26,7 @@ use crate::utils::exec::command; use crate::utils::helpers::{ self, exe, get_clang_cl_resource_dir, libdir, t, unhashed_basename, up_to_date, }; -use crate::{CLang, GitRepo, exit, trace}; +use crate::{CLang, GitRepo, trace}; /// Result of building or downloading LLVM artifacts. #[derive(Clone)] @@ -1034,7 +1034,7 @@ impl CommandLineStep for RustOffload { "`{lib_rust_offload}` not found in `{}`. Either the build has failed or RustOffload was built with a wrong version of LLVM", build_dir.display() ); - exit!(1); + helpers::exit_process(1); } BuiltRustOffload { offload: dylib } @@ -1266,7 +1266,7 @@ impl CommandLineStep for OmpOffload { "`{p:?}` not found in `{}`. Either the build has failed or Offload was built with a wrong version of LLVM", out_dir.display() ); - exit!(1); + helpers::exit_process(1); } } BuiltOmpOffload { offload: files } @@ -1414,7 +1414,7 @@ impl CommandLineStep for Enzyme { "`{libenzyme}` not found in `{}`. Either the build has failed or Enzyme was built with a wrong version of LLVM", build_dir.display() ); - exit!(1); + helpers::exit_process(1); } t!(stamp.write()); diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index c7825ed1a0345..82a132d0b5288 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -8,6 +8,7 @@ use std::path::PathBuf; use build_helper::git::get_git_untracked_files; use clap_complete::{Generator, shells}; +use crate::Mode; use crate::core::build_steps::dist::distdir; use crate::core::build_steps::test; use crate::core::build_steps::tool::{self, RustcPrivateCompilers, SourceType, Tool}; @@ -16,8 +17,7 @@ use crate::core::builder::{Builder, CommandLineStep, Kind, RunConfig, ShouldRun, use crate::core::config::TargetSelection; use crate::core::config::flags::{get_completion, top_level_help}; use crate::utils::exec::command; -use crate::utils::helpers::t; -use crate::{Mode, exit}; +use crate::utils::helpers::{self, t}; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct BuildManifest; @@ -138,7 +138,7 @@ impl CommandLineStep for Miri { if stage == 0 { eprintln!("ERROR: miri cannot be run at stage 0"); - exit!(1); + helpers::exit_process(1); } // Miri always runs on the host, because it can interpret code for any target diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 1ddcb43a68588..27a400406e144 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -143,7 +143,7 @@ impl CommandLineStep for Profile { } _ => { println!("Exiting."); - crate::exit!(1); + helpers::exit_process(1); } } } @@ -415,7 +415,7 @@ pub fn interactive_path() -> io::Result { io::stdin().read_line(&mut input)?; if input.is_empty() { eprintln!("EOF on stdin, when expecting answer to question. Giving up."); - crate::exit!(1); + helpers::exit_process(1); } break match parse_with_abbrev(&input) { Ok(profile) => profile, diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index dca3220acda55..762bf0a271704 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -45,7 +45,7 @@ use crate::utils::helpers::{ up_to_date, }; use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests}; -use crate::{CLang, CodegenBackendKind, GitRepo, Mode, TestTarget, envify, exit}; +use crate::{CLang, CodegenBackendKind, GitRepo, Mode, TestTarget, envify}; mod compiletest; pub mod failed_tests; @@ -291,7 +291,7 @@ impl CommandLineStep for Cargotest { eprintln!( "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1." ); - exit!(1); + helpers::exit_process(1); } // We want to build cargo stage N (where N == top_stage), and rustc stage N, // and test both of these together. @@ -948,7 +948,7 @@ impl CommandLineStep for CompiletestTest { ERROR: `--stage 0` causes compiletest to query information from the stage0 (precompiled) compiler, instead of the in-tree compiler, which can cause some tests to fail inappropriately NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `--set build.compiletest-allow-stage0=true`." ); - crate::exit!(1); + helpers::exit_process(1); } let bootstrap_compiler = builder.compiler(0, host); @@ -1297,7 +1297,7 @@ impl CommandLineStep for Clippy { } if !builder.config.cmd.bless() { - crate::exit!(1); + helpers::exit_process(1); } } @@ -1702,7 +1702,7 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to PATH = inferred_rustfmt_dir.display(), CHAN = builder.config.channel, ); - crate::exit!(1); + helpers::exit_process(1); }; let all = false; crate::core::build_steps::format::format( @@ -1733,7 +1733,7 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to eprintln!( "x.py completions were changed; run `x.py run generate-completions` to update them" ); - crate::exit!(1); + helpers::exit_process(1); } builder.info("x.py help check"); @@ -1743,13 +1743,13 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to let help_path = get_help_path(builder); let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| { eprintln!("couldn't read {}: {}", help_path.display(), err); - crate::exit!(1); + helpers::exit_process(1); }); let new_help = top_level_help(); if new_help != cur_help { eprintln!("x.py help was changed; run `x.py run generate-help` to update it"); - crate::exit!(1); + helpers::exit_process(1); } } } @@ -2232,7 +2232,7 @@ ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not yo HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `--set build.compiletest-allow-stage0=true`." ); - crate::exit!(1); + helpers::exit_process(1); } let mut test_compiler = self.test_compiler; @@ -2443,7 +2443,7 @@ ERROR: No configured backend named `{name}` HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`", name = codegen_backend.name(), ); - crate::exit!(1); + helpers::exit_process(1); } if let CodegenBackendKind::Gcc = codegen_backend @@ -4806,14 +4806,14 @@ impl CommandLineStep for StdSemverCheck { ); if builder.fail_fast { eprintln!("{error}",); - exit!(1); + helpers::exit_process(1); } else { builder.config.exec_ctx().add_to_delay_failure(error); } } _ => { eprintln!("cargo-semver-checks failed.\n{}\n{}", res.stderr(), res.stdout()); - exit!(1); + helpers::exit_process(1); } } } diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 101309cc2451d..3605fcf5b2fa6 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -22,7 +22,7 @@ use crate::core::builder::{ }; use crate::core::config::{Allocator, DebuginfoLevel, RustcLto, TargetSelection}; use crate::utils::exec::{BootstrapCommand, command}; -use crate::utils::helpers::{add_dylib_path, exe, t}; +use crate::utils::helpers::{self, add_dylib_path, exe, t}; use crate::{Compiler, FileType, Mode}; #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -160,7 +160,7 @@ impl Step for ToolBuild { ); if !build_success { - crate::exit!(1); + helpers::exit_process(1); } else { // HACK(#82501): on Windows, the tools directory gets added to PATH when running tests, and // compiletest confuses HTML tidy with the in-tree tidy. Name the in-tree tidy something diff --git a/src/bootstrap/src/core/build_steps/toolstate.rs b/src/bootstrap/src/core/build_steps/toolstate.rs index 73b6863248df0..c07bbc5d54e78 100644 --- a/src/bootstrap/src/core/build_steps/toolstate.rs +++ b/src/bootstrap/src/core/build_steps/toolstate.rs @@ -92,7 +92,7 @@ fn print_error(tool: &str, submodule: &str) { eprintln!("If you do NOT intend to update '{tool}', please ensure you did not accidentally"); eprintln!("change the submodule at '{submodule}'. You may ask your reviewer for the"); eprintln!("proper steps."); - crate::exit!(3); + helpers::exit_process(3); } fn check_changed_files(builder: &Builder<'_>, toolstates: &HashMap, ToolState>) { @@ -170,7 +170,7 @@ impl CommandLineStep for ToolStateCheck { } if did_error { - crate::exit!(1); + helpers::exit_process(1); } check_changed_files(builder, &toolstates); @@ -214,7 +214,7 @@ impl CommandLineStep for ToolStateCheck { } if did_error { - crate::exit!(1); + helpers::exit_process(1); } if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() { diff --git a/src/bootstrap/src/core/builder/cli_paths.rs b/src/bootstrap/src/core/builder/cli_paths.rs index 51304bcd140b6..f8207dbf5a480 100644 --- a/src/bootstrap/src/core/builder/cli_paths.rs +++ b/src/bootstrap/src/core/builder/cli_paths.rs @@ -2,44 +2,22 @@ //! command-line, extracted from `core/builder/mod.rs` because that file is //! large and hard to navigate. -use std::fmt::{self, Debug}; +use std::collections::{HashMap, HashSet}; +use std::hash::Hash; use std::path::PathBuf; use crate::core::builder::{Builder, CommandLineStepDescription, Kind, PathSet, ShouldRun}; +use crate::utils::helpers; #[cfg(test)] mod tests; -#[derive(Clone, PartialEq)] -pub(crate) struct CLIStepPath { - pub(crate) path: PathBuf, - pub(crate) will_be_executed: bool, -} - -impl Debug for CLIStepPath { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.path.display()) - } -} - -impl From for CLIStepPath { - fn from(path: PathBuf) -> Self { - Self { path, will_be_executed: false } - } -} - /// Combines a [`CommandLineStepDescription`] with its corresponding [`ShouldRun`]. struct StepExtra<'a> { desc: &'a CommandLineStepDescription, should_run: ShouldRun<'a>, } -struct StepToRun<'a> { - sort_index: usize, - desc: &'a CommandLineStepDescription, - pathsets: Vec, -} - pub(crate) fn match_paths_to_steps_and_run( builder: &Builder<'_>, step_descs: &[CommandLineStepDescription], @@ -59,7 +37,7 @@ pub(crate) fn match_paths_to_steps_and_run( "ERROR: '{}' subcommand is incompatible with `rust.download-rustc`.", builder.kind.as_str() ); - crate::exit!(1); + helpers::exit_process(1); } // sanity checks on rules @@ -67,6 +45,7 @@ pub(crate) fn match_paths_to_steps_and_run( assert!(!should_run.paths.is_empty(), "{:?} should have at least one pathset", desc.name); } + // Run default steps if appropriate. if paths.is_empty() || builder.config.include_default_paths { for StepExtra { desc, should_run } in &steps { if (desc.is_default_step_fn)(builder) { @@ -86,7 +65,7 @@ pub(crate) fn match_paths_to_steps_and_run( // // It is also possible that someone passed a relative path starting with . or .. // In that case, we have to remove that path prefix. - let mut paths = paths + let paths = paths .iter() .map(|path| { // Here we "launder" the path through builder.src, to normalize relative path prefixes @@ -111,7 +90,6 @@ pub(crate) fn match_paths_to_steps_and_run( path } }) - .map(|p| p.to_owned()) .collect::>(); // If any absolute paths couldn't be made relative, stop now and report them. @@ -120,69 +98,51 @@ pub(crate) fn match_paths_to_steps_and_run( eprintln!( "ERROR: the following paths do not exist on disk or point outside the source directory: {bad_abs_paths:#?}" ); - crate::exit!(1); + helpers::exit_process(1); } - // Handle all test suite paths. - // (This is separate from the loop below to avoid having to handle multiple paths in `is_suite_path` somehow.) - paths.retain(|path| { - for StepExtra { desc, should_run } in &steps { - if let Some(suite) = should_run.is_suite_path(path) { - desc.maybe_run(builder, vec![suite.clone()]); - return false; - } - } - true - }); - - if paths.is_empty() { - return; - } - - let mut paths: Vec = paths.into_iter().map(|p| p.into()).collect(); - let mut path_lookup: Vec<(CLIStepPath, bool)> = - paths.clone().into_iter().map(|p| (p, false)).collect(); - - // Before actually running (non-suite) steps, collect them into a list of structs - // so that we can then sort the list to preserve CLI order as much as possible. - let mut steps_to_run = vec![]; - - for StepExtra { desc, should_run } in &steps { - let pathsets = should_run.pathsets_for_paths_flagging_matches(&mut paths); - - // This value is used for sorting the step execution order. - // By default, `usize::MAX` is used as the index for steps to assign them the lowest priority. - // - // If we resolve the step's path from the given CLI input, this value will be updated with - // the step's actual index. - let mut closest_index = usize::MAX; - - // Find the closest index from the original list of paths given by the CLI input. - for (index, (path, is_used)) in path_lookup.iter_mut().enumerate() { - if !*is_used && !paths.contains(path) { - closest_index = index; - *is_used = true; - break; + // When matching selectors to steps, we want to balance two conflicting goals: + // - Ideally, steps should run in the order specified by command-line arguments. + // - A selected step should be invoked only once, not multiple times. + // + // We therefore build up: + // - An ordered list of steps to run, each represented by its index in `steps`. + // - For each step (by index), the list of its anchors that were matched. + let mut step_queue = Vec::::with_capacity(paths.len()); + let mut step_anchors = HashMap::>::with_capacity(steps.len()); + let mut unmatched_paths = vec![]; + + // For each command-line selector, enqueue the steps that it matches. + for path in &paths { + let mut path_matched = false; + + for (step_ix, step) in steps.iter().enumerate() { + let matched_anchors = step + .should_run + .paths + .iter() + .filter(|anchor| { + // The extra `starts_with` here allows an argument like + // `tests/ui/asm/cfg.rs` to select the suite anchor `tests/ui`. + anchor.has(path) + || matches!(anchor, PathSet::Suite(suite) if path.starts_with(&suite.path)) + }) + .collect::>(); + + if !matched_anchors.is_empty() { + step_queue.push(step_ix); + step_anchors.entry(step_ix).or_default().extend(matched_anchors); + path_matched = true; } } - steps_to_run.push(StepToRun { sort_index: closest_index, desc, pathsets }); - } - - // Sort the steps before running them to respect the CLI order. - steps_to_run.sort_by_key(|step| step.sort_index); - - // Handle all PathSets. - for StepToRun { sort_index: _, desc, pathsets } in steps_to_run { - if !pathsets.is_empty() { - desc.maybe_run(builder, pathsets); + if !path_matched { + unmatched_paths.push(path); } } - paths.retain(|p| !p.will_be_executed); - - if !paths.is_empty() { - eprintln!("ERROR: no `{}` rules matched {:?}", builder.kind.as_str(), paths); + if !unmatched_paths.is_empty() { + eprintln!("ERROR: no `{}` rules matched {unmatched_paths:?}", builder.kind.as_str()); eprintln!( "HELP: run `x.py {} --help --verbose` to show a list of available paths", builder.kind.as_str() @@ -190,6 +150,25 @@ pub(crate) fn match_paths_to_steps_and_run( eprintln!( "NOTE: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`" ); - crate::exit!(1); + helpers::exit_process(1); + } + + fn dedup_vec(vec: &mut Vec) { + let mut seen = HashSet::::with_capacity(vec.len()); + vec.retain(|&x| seen.insert(x)); + } + + // Deduplicate the queue of steps to run, and the list of anchors to run for each step. + dedup_vec(&mut step_queue); + for anchors in step_anchors.values_mut() { + dedup_vec(anchors); + } + + // Run the steps that were selected, in (roughly) command-line order. + // For each step, pass all of its matched anchors, regardless of position. + for &step_ix in &step_queue { + let step = &steps[step_ix]; + let anchors = step_anchors[&step_ix].iter().map(|p| PathSet::clone(p)).collect::>(); + step.desc.maybe_run(builder, anchors); } } diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library_core_and_alloc_and_stdarch.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library_core_and_alloc_and_stdarch.snap index 2664ab7a404cc..ad349efdde6e7 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library_core_and_alloc_and_stdarch.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library_core_and_alloc_and_stdarch.snap @@ -4,8 +4,8 @@ expression: test library/core library/alloc library/stdarch --- [Test] test::Crate targets: [aarch64-unknown-linux-gnu] - - Set({library/alloc}) - Set({library/core}) + - Set({library/alloc}) [Test] test::StdarchVerify targets: [x86_64-unknown-linux-gnu] - Set({library/stdarch/crates/stdarch-verify}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_coverage_trivial_rs.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_coverage_trivial_rs.snap new file mode 100644 index 0000000000000..8b78c288a550a --- /dev/null +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_coverage_trivial_rs.snap @@ -0,0 +1,7 @@ +--- +source: src/bootstrap/src/core/builder/cli_paths/tests.rs +expression: test tests/coverage/trivial.rs +--- +[Test] test::Coverage + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/coverage) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_coverage_trivial_rs_and_attr_impl_rs.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_coverage_trivial_rs_and_attr_impl_rs.snap new file mode 100644 index 0000000000000..4e11821b7cbcb --- /dev/null +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_coverage_trivial_rs_and_attr_impl_rs.snap @@ -0,0 +1,7 @@ +--- +source: src/bootstrap/src/core/builder/cli_paths/tests.rs +expression: test tests/coverage/trivial.rs tests/coverage/attr/impl.rs +--- +[Test] test::Coverage + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/coverage) diff --git a/src/bootstrap/src/core/builder/cli_paths/tests.rs b/src/bootstrap/src/core/builder/cli_paths/tests.rs index b4dad0013b2de..e18a274c75f49 100644 --- a/src/bootstrap/src/core/builder/cli_paths/tests.rs +++ b/src/bootstrap/src/core/builder/cli_paths/tests.rs @@ -197,6 +197,11 @@ declare_tests!( (x_test_src_tools_miri, "test src/tools/miri"), (x_test_src_tools_miri_and_cargo_miri, "test src/tools/miri src/tools/miri/cargo-miri"), (x_test_tests, "test tests"), + (x_test_tests_coverage_trivial_rs, "test tests/coverage/trivial.rs"), + ( + x_test_tests_coverage_trivial_rs_and_attr_impl_rs, + "test tests/coverage/trivial.rs tests/coverage/attr/impl.rs" + ), (x_test_tests_skip_coverage, "test tests --skip=coverage"), (x_test_tests_ui, "test tests/ui"), (x_test_tests_ui_dot_prefix, "test ./tests/ui"), diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 8d0461f0787ed..c21322740fa61 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -20,7 +20,6 @@ use crate::core::build_steps::tool::RustcPrivateCompilers; use crate::core::build_steps::{ check, clean, clippy, compile, dist, doc, gcc, install, llvm, run, setup, test, tool, vendor, }; -use crate::core::builder::cli_paths::CLIStepPath; use crate::core::builder::step_stack::StepRecord; pub use crate::core::builder::step_stack::StepStack; use crate::core::config::flags::Subcommand; @@ -361,7 +360,7 @@ struct CommandLineStepDescription { kind: Kind, } -#[derive(Clone, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash)] pub struct TaskPath { pub path: PathBuf, } @@ -373,7 +372,7 @@ impl Debug for TaskPath { } /// Collection of paths used to match a task rule. -#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)] pub enum PathSet { /// A collection of individual paths or aliases. /// @@ -415,34 +414,6 @@ impl PathSet { p.path.ends_with(needle) || p.path.starts_with(needle) } - /// Returns true if self is matched by any of the command-line selectors, - /// and mutates those selectors to flag them as will-be-executed. - fn match_and_flag_selectors(&self, selectors: &mut [CLIStepPath]) -> bool { - let mut check_and_flag = |p| { - let mut result = false; - for selector in selectors.iter_mut() { - let matched = Self::check(p, &selector.path); - if matched { - selector.will_be_executed = true; - result = true; - } - } - result - }; - - match self { - PathSet::Set(set) => { - // Flag all matching selectors, not just the first match. - let mut matched = false; - for p in set { - matched |= check_and_flag(p); - } - matched - } - PathSet::Suite(suite) => check_and_flag(suite), - } - } - /// A convenience wrapper for Steps which know they have no aliases and all their sets contain only a single path. /// /// This can be used with [`ShouldRun::crate_or_deps`], [`ShouldRun::path`], or [`ShouldRun::alias`]. @@ -633,38 +604,11 @@ impl<'a> ShouldRun<'a> { self } - /// Handles individual files (not directories) within a test suite. - fn is_suite_path(&self, requested_path: &Path) -> Option<&PathSet> { - self.paths.iter().find(|pathset| match pathset { - PathSet::Suite(suite) => requested_path.starts_with(&suite.path), - PathSet::Set(_) => false, - }) - } - pub fn suite_path(mut self, suite: &str) -> Self { self.paths.insert(PathSet::Suite(TaskPath { path: suite.into() })); self } - /// Given a set of requested paths, return the subset which match the Step for this `ShouldRun`, - /// removing the matches from `paths`. - /// - /// NOTE: this returns multiple PathSets to allow for the possibility of multiple units of work - /// within the same step. For example, `test::Crate` allows testing multiple crates in the same - /// cargo invocation, which are put into separate sets because they aren't aliases. - /// - /// The reason we return PathSet instead of PathBuf is to allow for aliases that mean the same thing - /// (for now, just `all_krates` and `paths`, but we may want to add an `aliases` function in the future?) - fn pathsets_for_paths_flagging_matches(&self, paths: &mut [CLIStepPath]) -> Vec { - let mut sets = vec![]; - for pathset in &self.paths { - if pathset.match_and_flag_selectors(paths) { - sets.push(pathset.clone()); - } - } - sets - } - /// When the corresponding step is run "by default" (without explicit command-line paths), /// act as though the user had explicitly specified these paths. fn default_pathsets(&self) -> Vec { diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 4ae1ee53537f2..499900226d026 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -2119,11 +2119,11 @@ mod snapshot { [test] compiletest-run-make 2 [build] rustc 1 -> rustc 2 [build] rustdoc 1 + [build] rustc 2 -> std 2 + [build] rustdoc 2 [build] rustc 0 -> RustdocGUITest 1 [test] rustdoc-gui 2 [test] compiletest-incremental 2 - [build] rustc 2 -> std 2 - [build] rustdoc 2 "); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index fc69eada5eb02..e8788f2dd498d 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -58,7 +58,7 @@ use crate::core::download::{DownloadContext, download_beta_toolchain, is_downloa use crate::utils::channel::{self, GitInfo}; use crate::utils::exec::{ExecutionContext, command}; use crate::utils::helpers::{self, exe, fail, get_host_target, t}; -use crate::{CodegenBackendKind, check_ci_llvm, exit}; +use crate::{CodegenBackendKind, check_ci_llvm}; /// Each path in this list is considered "allowed" in the `download-rustc="if-unchanged"` logic. /// This means they can be modified and changes to these paths should never trigger a compiler build @@ -1225,7 +1225,7 @@ impl Config { eprintln!( "ERROR: cannot {kind} anything on stage 0. Use at least stage 1 or set build.local-rebuild=true and use a stage0 compiler built from in-tree sources." ); - exit!(1); + helpers::exit_process(1); } }; @@ -1253,14 +1253,14 @@ impl Config { eprintln!( "ERROR: cannot test anything on stage 0. Use at least stage 1. If you want to run compiletest with an external stage0 toolchain, enable `build.compiletest-allow-stage0`." ); - exit!(1); + helpers::exit_process(1); } _ => {} } if flags_compile_time_deps && !matches!(flags_cmd, Subcommand::Check { .. }) { eprintln!("ERROR: Can't use --compile-time-deps with any subcommand other than check."); - exit!(1); + helpers::exit_process(1); } if matches!(flags_cmd, Subcommand::Fix) { @@ -1812,7 +1812,7 @@ NOTE: Please add `--stage 2` to your command line, or if you're sure you want to } Err(e) => { eprintln!("ERROR: Failed to parse CI rustc bootstrap.toml: {e}"); - exit!(2); + helpers::exit_process(2); } }; @@ -2261,7 +2261,7 @@ fn postprocess_toml( "ERROR: Failed to parse default config profile at '{}': {e}", include_path.display() ); - exit!(2); + helpers::exit_process(2); }); toml.merge( Some(include_path), @@ -2303,7 +2303,7 @@ fn postprocess_toml( } } eprintln!("failed to parse override `{option}`: `{err}"); - exit!(2); + helpers::exit_process(2); } toml.merge(None, &mut Default::default(), override_toml, ReplaceOpt::Override); } @@ -2411,7 +2411,7 @@ pub fn download_ci_rustc_commit<'a>( println!( "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources." ); - crate::exit!(1); + helpers::exit_process(1); } true @@ -2504,7 +2504,7 @@ pub fn parse_download_ci_llvm<'a>( if rust_info.is_from_tarball() { // Git is needed for running "if-unchanged" logic. println!("ERROR: 'if-unchanged' is only compatible with Git managed sources."); - crate::exit!(1); + helpers::exit_process(1); } // Fetching the LLVM submodule is unnecessary for self-tests. @@ -2774,7 +2774,7 @@ fn bad_config(toml_path: &Path, e: toml::de::Error) -> ! { } } - exit!(2); + helpers::exit_process(2); } #[derive(Copy, Clone, Debug)] diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index fba3a9fe74705..fa6225f6649e5 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -15,6 +15,7 @@ use crate::core::build_steps::setup::Profile; use crate::core::builder::{Builder, Kind}; use crate::core::config::Config; use crate::core::config::target_selection::{TargetSelectionList, target_selection_list}; +use crate::utils::helpers; use crate::{Build, CodegenBackendKind, TestTarget}; #[derive(Copy, Clone, Default, Debug, ValueEnum)] @@ -740,7 +741,7 @@ pub fn get_completion(shell: &dyn Generator, path: &Path) -> Option { } else { std::fs::read_to_string(path).unwrap_or_else(|_| { eprintln!("couldn't read {}", path.display()); - crate::exit!(1); + helpers::exit_process(1); }) }; let mut buf = Vec::new(); diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs index db901434a47e8..ecb62af4adc13 100644 --- a/src/bootstrap/src/core/config/mod.rs +++ b/src/bootstrap/src/core/config/mod.rs @@ -42,7 +42,7 @@ pub use toml::change_id::ChangeId; pub use toml::rust::BootstrapOverrideLld; pub use toml::target::Target; -use crate::exit; +use crate::utils::helpers; // We are using a decl macro instead of a derive proc macro here to reduce the compile time of bootstrap. #[macro_export] @@ -88,7 +88,7 @@ macro_rules! define_config { panic!("overriding existing option") } else { eprintln!("overriding existing option: `{}`", stringify!($field)); - $crate::exit!(2); + $crate::utils::helpers::exit_process(2); } } else { self.$field = other.$field; @@ -214,7 +214,7 @@ impl Merge for Option { panic!("overriding existing option") } else { eprintln!("overriding existing option"); - exit!(2); + helpers::exit_process(2); } } else { *self = other; diff --git a/src/bootstrap/src/core/config/toml/mod.rs b/src/bootstrap/src/core/config/toml/mod.rs index 8629f143e9106..3d31f80ebe496 100644 --- a/src/bootstrap/src/core/config/toml/mod.rs +++ b/src/bootstrap/src/core/config/toml/mod.rs @@ -34,9 +34,8 @@ use target::TomlTarget; use crate::core::config::toml::pgo::Pgo; use crate::core::config::{Config, Merge, ReplaceOpt}; -use crate::exit; use crate::utils::change_tracker::{find_recent_config_change_ids, human_readable_changes}; -use crate::utils::helpers::t; +use crate::utils::helpers::{self, t}; /// Structure of the `bootstrap.toml` file that configuration is read from. /// @@ -126,12 +125,12 @@ impl Merge for TomlConfig { let include_path = parent_dir.join(include_path); let include_path = include_path.canonicalize().unwrap_or_else(|e| { eprintln!("ERROR: Failed to canonicalize '{}' path: {e}", include_path.display()); - exit!(2); + helpers::exit_process(2); }); let included_toml = Config::get_toml_inner(&include_path).unwrap_or_else(|e| { eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display()); - exit!(2); + helpers::exit_process(2); }); assert!( diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs index 4a4de50a5deaa..1d50adec38a1c 100644 --- a/src/bootstrap/src/core/config/toml/rust.rs +++ b/src/bootstrap/src/core/config/toml/rust.rs @@ -11,7 +11,8 @@ use crate::core::config::toml::TomlConfig; use crate::core::config::{ CompressDebuginfo, DebuginfoLevel, Merge, ReplaceOpt, StringOrBool, TargetSelection, }; -use crate::{CodegenBackendKind, define_config, exit}; +use crate::utils::helpers; +use crate::{CodegenBackendKind, define_config}; define_config! { /// TOML representation of how the Rust build is configured. @@ -463,7 +464,7 @@ pub(crate) fn parse_codegen_backends( if !BUILTIN_CODEGEN_BACKENDS.contains(&backend.name()) { if CiEnv::is_rust_lang_managed_ci_job() { eprintln!("Unknown codegen backend {}", backend.name()); - exit!(1); + helpers::exit_process(1); } println!( @@ -476,7 +477,7 @@ pub(crate) fn parse_codegen_backends( } if found_backends.is_empty() { eprintln!("ERROR: `{section}.codegen-backends` should not be set to `[]`"); - exit!(1); + helpers::exit_process(1); } found_backends } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 665a976fe8cea..0b3f43a7e79ef 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -14,10 +14,9 @@ use xz2::bufread::XzDecoder; use crate::core::build_steps::llvm::detect_llvm_freshness; use crate::core::config::toml::llvm::check_incompatible_options_for_ci_llvm; use crate::core::config::{BUILDER_CONFIG_FILENAME, Config, TargetSelection}; -use crate::exit; use crate::utils::build_stamp::BuildStamp; use crate::utils::exec::{ExecutionContext, command}; -use crate::utils::helpers::{exe, hex_encode, move_file, t}; +use crate::utils::helpers::{self, exe, hex_encode, move_file, t}; static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock = OnceLock::new(); @@ -294,7 +293,7 @@ impl Config { eprintln!("HELP: maybe your repository history is too shallow?"); eprintln!("HELP: consider disabling `download-ci-llvm`"); eprintln!("HELP: or fetch enough history to include one upstream commit"); - crate::exit!(1); + helpers::exit_process(1); } }; let stamp_key = format!("{}{}", llvm_sha, self.llvm_assertions); @@ -350,7 +349,7 @@ impl Config { } Err(e) => { eprintln!("ERROR: Failed to parse CI LLVM bootstrap.toml: {e}"); - exit!(2); + helpers::exit_process(2); } }; }; @@ -1121,7 +1120,7 @@ fn download_http_with_retries( if !help_on_error.is_empty() { eprintln!("{help_on_error}"); } - crate::exit!(1); + helpers::exit_process(1); } } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index c043dc3944f18..0256aabe54edb 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -19,7 +19,7 @@ use crate::core::build_steps::tool; use crate::core::builder::Builder; use crate::core::config::{CompilerBuiltins, DebuggerPath, Subcommand, Target}; use crate::utils::exec::command; -use crate::utils::helpers::t; +use crate::utils::helpers::{self, t}; pub struct Finder { cache: HashMap>, @@ -161,7 +161,7 @@ You should install cmake, or set `download-ci-llvm = true` in the than building it. " ); - crate::exit!(1); + helpers::exit_process(1); } build.config.python = build diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index c084c12ae4ab8..eb68daa0cf074 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -15,7 +15,11 @@ //! //! More documentation can be found in each respective module below, and you can //! also check out the `src/bootstrap/README.md` file for more information. + +// tidy-alphabetical-start #![allow(clippy::assertions_on_constants, reason = "false positive for `assert!(cfg!(..))`")] +#![allow(clippy::map_clone, reason = "false positive for `|x: &&Foo| Foo::clone(x)`")] +// tidy-alphabetical-end use std::cell::Cell; use std::collections::{BTreeSet, HashMap, HashSet}; @@ -688,7 +692,7 @@ impl Build { "submodule {submodule} does not appear to be checked out, \ but it is required for this step{maybe_enable}{err_hint}" ); - exit!(1); + helpers::exit_process(1); } } @@ -751,7 +755,7 @@ impl Build { let builder = builder::Builder::new(self); let rustfmt_path = builder.ensure(InternalRustfmt).unwrap_or_else(|| { eprintln!("fmt error: `x fmt` is not supported on this channel"); - crate::exit!(1); + helpers::exit_process(1); }); return core::build_steps::format::format( &builder, @@ -1686,7 +1690,7 @@ impl Build { "ERROR: Unable to find the stamp file {}, did you try to keep a nonexistent build stage?", stamp.path().display() ); - crate::exit!(1); + helpers::exit_process(1); } let mut paths = Vec::new(); @@ -1961,7 +1965,7 @@ Alternatively, set `download-ci-llvm = true` in that `[llvm]` section to download LLVM rather than building it. " ); - exit!(1); + helpers::exit_process(1); } } @@ -2085,10 +2089,3 @@ pub fn prepare_behaviour_dump_dir(build: &Build) { t!(INITIALIZED.set(true)); } } - -#[macro_export] -macro_rules! exit { - ($code:expr) => { - $crate::utils::helpers::detail_exit($code, cfg!(test)); - }; -} diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index 0f8f7550045c0..55088e9bf219c 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -25,8 +25,7 @@ use std::time::{Duration, Instant}; use build_helper::drop_bomb::DropBomb; use crate::core::config::DryRun; -use crate::exit; -use crate::utils::helpers::t; +use crate::utils::helpers::{self, t}; /// What should be done when the command fails. #[derive(Debug, Copy, Clone)] @@ -657,7 +656,7 @@ impl ExecutionContext { for failure in &*failures { eprintln!(" - {failure}"); } - exit!(1); + helpers::exit_process(1); } /// Execute a command and return its output. @@ -747,7 +746,7 @@ impl ExecutionContext { if !self.is_verbose() { println!("Command has failed. Rerun with -v to see more details."); } - exit!(1); + helpers::exit_process(1); } /// Spawns the command with configured stdout and stderr handling. diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 4ad5ffe38d42b..021763fdb371a 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -571,11 +571,16 @@ pub fn set_file_times>(path: P, times: fs::FileTimes) -> io::Resu f.set_times(times) } -/// If code is not 0 (successful exit status), exit status is 101 (rust's default error code.) -/// If `is_test` true and code is an error code, it will cause a panic. -pub fn detail_exit(code: i32, is_test: bool) -> ! { - // if in test and code is an error code, panic with status code provided - if is_test { +/// Exits the process by calling [`std::process::exit`]. +/// +/// In CI, extra information will be printed to make failures easier to investigate. +/// +/// If `cfg!(test)` is true, this will panic instead of exiting the process. +/// Doing so avoids disturbing other tests in the process, and allows `#[should_panic]` +/// to detect expected failures. +pub(crate) fn exit_process(code: i32) -> ! { + // In bootstrap unit tests, panic instead of killing the whole test process. + if cfg!(test) { panic!("status code: {code}"); } else { // If we're in CI, print the current bootstrap invocation command, to make it easier to @@ -600,5 +605,5 @@ pub fn detail_exit(code: i32, is_test: bool) -> ! { pub fn fail(s: &str) -> ! { eprintln!("\n\n{s}\n\n"); - detail_exit(1, cfg!(test)); + exit_process(1); } diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index 9062760a74fd5..7f4f98459acab 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -16,6 +16,7 @@ use termcolor::{Color, ColorSpec, WriteColor}; use crate::core::build_steps::test::failed_tests::RecordFailedTests; use crate::core::builder::Builder; use crate::utils::exec::BootstrapCommand; +use crate::utils::helpers; const TERSE_TESTS_PER_LINE: usize = 88; @@ -43,7 +44,7 @@ pub(crate) fn try_run_tests( } if builder.fail_fast { - crate::exit!(1); + helpers::exit_process(1); } builder.config.exec_ctx().add_to_delay_failure(format!("{cmd:?}")); diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs index 1978a68dd959c..3b9c345fc27f5 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs @@ -5,9 +5,6 @@ mod proc_macros; use rustc_codegen_ssa::back::metadata::DefaultMetadataLoader; use rustc_interface::util::rustc_version_str; use rustc_proc_macro::bridge; -use rustc_session::config::host_tuple; -use rustc_target::spec::{Target, TargetTuple}; -use std::path::Path; use std::{fs, io, time::SystemTime}; use temp_dir::TempDir; @@ -78,11 +75,7 @@ struct ProcMacroLibrary { impl ProcMacroLibrary { fn open(path: &Utf8Path) -> io::Result { let proc_macros = rustc_span::create_default_session_globals_then(|| { - let (target, _) = - Target::search(&TargetTuple::from_tuple(host_tuple()), Path::new(""), false) - .unwrap(); rustc_metadata::locator::get_proc_macros( - &target, path.as_ref(), &DefaultMetadataLoader, rustc_version_str().unwrap_or("unknown"), diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index 2a3a1bc002601..28570e1af4426 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -21,9 +21,7 @@ extern crate rustc_interface; extern crate rustc_lexer; extern crate rustc_metadata; extern crate rustc_proc_macro; -extern crate rustc_session; extern crate rustc_span; -extern crate rustc_target; mod bridge; mod dylib; diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 1b930f3249c6c..117de57d03dd4 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -16,6 +16,8 @@ use std::num::NonZeroU32; use std::path::{Path, PathBuf}; use std::{fmt, fs}; +use regex::Regex; + use crate::diagnostics::{RunningCheck, TidyCtx}; use crate::walk::{filter_dirs, filter_not_rust, walk, walk_many}; @@ -23,8 +25,9 @@ use crate::walk::{filter_dirs, filter_not_rust, walk, walk_many}; mod tests; mod version; -use regex::Regex; -use version::Version; +// Re-export Version. This means other crates can construct Versions from [u32;3] and from &str. +// This is useful for filtering for features older/newer than a user-provided value. +pub use version::Version; const FEATURE_GROUP_START_PREFIX: &str = "// feature-group-start"; const FEATURE_GROUP_END_PREFIX: &str = "// feature-group-end"; diff --git a/tests/crashes/148630.rs b/tests/crashes/148630.rs deleted file mode 100644 index 7b857bbb408a1..0000000000000 --- a/tests/crashes/148630.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #148630 -#![feature(unboxed_closures)] - -trait Tr {} -trait Foo { - fn foo() -> impl Sized - where - for<'a> <() as FnOnce<&'a i32>>::Output: Tr, - { - } -} - -fn main() {} diff --git a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.rs b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.rs index f62f8396e9911..c9f726e48d47e 100644 --- a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.rs +++ b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.rs @@ -14,5 +14,5 @@ pub(crate) const B: usize = 5; pub trait Tec: Bar {} pub struct Structure { //~ ERROR the trait bound `C: Bar<5>` is not satisfied - _field: C::BarType, //~ ERROR the trait bound `C: Bar<5>` is not satisfied + _field: C::BarType, } diff --git a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr index 045516d7d2ff6..b485e7b8d4c0d 100644 --- a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr +++ b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr @@ -9,17 +9,6 @@ help: consider further restricting type parameter `C` with trait `Bar` LL | pub struct Structure> { | ++++++++ -error[E0277]: the trait bound `C: Bar<5>` is not satisfied - --> $DIR/projections-in-super-trait-bound-unsatisfied.rs:17:13 - | -LL | _field: C::BarType, - | ^^^^^^^^^^ the trait `Bar<5>` is not implemented for `C` - | -help: consider further restricting type parameter `C` with trait `Bar` - | -LL | pub struct Structure> { - | ++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-59324.rs b/tests/ui/associated-types/issue-59324.rs index 9d4c7cb39ae9e..f9b310f6f9b31 100644 --- a/tests/ui/associated-types/issue-59324.rs +++ b/tests/ui/associated-types/issue-59324.rs @@ -11,14 +11,12 @@ pub trait Service { pub trait ThriftService: //~^ ERROR the trait bound `Bug: Foo` is not satisfied Service::OnlyFoo> -//~^ ERROR the trait bound `Bug: Foo` is not satisfied { fn get_service( //~^ ERROR the trait bound `Bug: Foo` is not satisfied //~| ERROR the trait bound `Bug: Foo` is not satisfied &self, ) -> Self::AssocType; - //~^ ERROR the trait bound `Bug: Foo` is not satisfied } fn with_factory(factory: dyn ThriftService<()>) {} diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index 3e2b0f4188973..929238dc29b15 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -12,18 +12,7 @@ LL | pub trait ThriftService: | +++++ error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:13:13 - | -LL | Service::OnlyFoo> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` - | -help: consider further restricting type parameter `Bug` with trait `Foo` - | -LL | pub trait ThriftService: - | +++++ - -error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:16:5 + --> $DIR/issue-59324.rs:15:5 | LL | / fn get_service( LL | | @@ -33,7 +22,7 @@ LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:24:29 + --> $DIR/issue-59324.rs:22:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` @@ -45,7 +34,7 @@ LL | pub trait Foo: NotFoo { | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:16:5 + --> $DIR/issue-59324.rs:15:5 | LL | / fn get_service( LL | | @@ -59,19 +48,8 @@ help: consider further restricting type parameter `Bug` with trait `Foo` LL | pub trait ThriftService: | +++++ -error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:20:10 - | -LL | ) -> Self::AssocType; - | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` - | -help: consider further restricting type parameter `Bug` with trait `Foo` - | -LL | pub trait ThriftService: - | +++++ - error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:24:29 + --> $DIR/issue-59324.rs:22:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` @@ -84,7 +62,7 @@ LL | pub trait Foo: NotFoo { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time - --> $DIR/issue-59324.rs:24:29 + --> $DIR/issue-59324.rs:22:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -101,6 +79,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn with_factory(factory: &dyn ThriftService<()>) {} | + -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/unique-closure-type-mismatch.stderr b/tests/ui/closures/unique-closure-type-mismatch.stderr index 3a31b6db4f62b..7d2a05b1d148b 100644 --- a/tests/ui/closures/unique-closure-type-mismatch.stderr +++ b/tests/ui/closures/unique-closure-type-mismatch.stderr @@ -18,6 +18,7 @@ LL | 1 => |c| c + 1, | ^ - type must be known at this point | = note: cannot satisfy `<_ as Add>::Output == _` + = note: the type must also implement `Add` help: consider giving this closure parameter an explicit type | LL | 1 => |c: /* Type */| c + 1, diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr index e0bf63f4b066d..366711e6d43c7 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr @@ -29,6 +29,7 @@ error[E0284]: type annotations needed for `([(); _], [(); 10])` LL | let (mut arr, mut arr_with_weird_len) = proj(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ type must be known at this point | + = note: cannot satisfy `::PROJ<_> == 10` note: required by a const generic parameter in `proj` --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:44:9 | diff --git a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs index bc7efac9dfccd..cfafca68bfd2f 100644 --- a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs +++ b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs @@ -19,10 +19,6 @@ trait Foo: Super //~| ERROR the size for values of type `Self` cannot be known where ::Assoc: Super, - //~^ ERROR type mismatch resolving - //~| ERROR the size for values of type `Self` cannot be known - //~| ERROR type mismatch resolving - //~| ERROR the size for values of type `Self` cannot be known { fn transmute(&self, t: T) -> ::Assoc; //~^ ERROR cannot find trait `B` in this scope diff --git a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr index cf00ee45a43e5..b8796f673f4a5 100644 --- a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr +++ b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr @@ -1,17 +1,17 @@ error[E0405]: cannot find trait `B` in this scope - --> $DIR/ice-generics-of-crate-root-152335.rs:27:43 + --> $DIR/ice-generics-of-crate-root-152335.rs:23:43 | LL | fn transmute(&self, t: T) -> ::Assoc; | ^ not found in this scope error[E0601]: `main` function not found in crate `ice_generics_of_crate_root_152335` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:57 + --> $DIR/ice-generics-of-crate-root-152335.rs:34:57 | LL | impl> Mirror for T {} | ^ consider adding a `main` function to `$DIR/ice-generics-of-crate-root-152335.rs` error[E0271]: type mismatch resolving `>::Assoc == Self` - --> $DIR/ice-generics-of-crate-root-152335.rs:27:5 + --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 | LL | fn transmute(&self, t: T) -> ::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `Self`, found type parameter `T` @@ -21,7 +21,7 @@ LL | fn transmute(&self, t: T) -> ::Assoc; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 | LL | impl> Mirror for T {} | --------- ^^^^^^ ^ @@ -29,13 +29,13 @@ LL | impl> Mirror for T {} | unsatisfied trait bound introduced here error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/ice-generics-of-crate-root-152335.rs:27:5 + --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 | LL | fn transmute(&self, t: T) -> ::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -69,7 +69,7 @@ LL | trait Foo: Super = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 | LL | impl> Mirror for T {} | --------- ^^^^^^ ^ @@ -83,49 +83,7 @@ LL | trait Foo: Super | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 - | -LL | impl> Mirror for T {} - | - ^^^^^^ ^ - | | - | unsatisfied trait bound implicitly introduced here -help: consider further restricting `Self` - | -LL | trait Foo: Super + Sized - | +++++++ - -error[E0271]: type mismatch resolving `>::Assoc == Self` - --> $DIR/ice-generics-of-crate-root-152335.rs:21:30 - | -LL | trait Foo: Super - | ------------------------------------------------ - | | | - | | found type parameter - | expected type parameter -... -LL | ::Assoc: Super, - | ^^^^^ expected type parameter `Self`, found type parameter `T` - | - = note: expected type parameter `Self` - found type parameter `T` - = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound - = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 - | -LL | impl> Mirror for T {} - | --------- ^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/ice-generics-of-crate-root-152335.rs:21:30 - | -LL | ::Assoc: Super, - | ^^^^^ doesn't have a size known at compile-time - | -note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -137,7 +95,7 @@ LL | trait Foo: Super + Sized | +++++++ error[E0046]: not all trait items implemented, missing: `Assoc` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:1 + --> $DIR/ice-generics-of-crate-root-152335.rs:34:1 | LL | type Assoc: ?Sized; | ------------------ `Assoc` from trait @@ -146,7 +104,7 @@ LL | impl> Mirror for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Assoc` in implementation error[E0271]: type mismatch resolving `>::Assoc == Self` - --> $DIR/ice-generics-of-crate-root-152335.rs:27:5 + --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 | LL | trait Foo: Super | ------------------------------------------------ @@ -162,7 +120,7 @@ LL | fn transmute(&self, t: T) -> ::Assoc; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 | LL | impl> Mirror for T {} | --------- ^^^^^^ ^ @@ -170,56 +128,13 @@ LL | impl> Mirror for T {} | unsatisfied trait bound introduced here error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/ice-generics-of-crate-root-152335.rs:27:5 + --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 | LL | fn transmute(&self, t: T) -> ::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 - | -LL | impl> Mirror for T {} - | - ^^^^^^ ^ - | | - | unsatisfied trait bound implicitly introduced here -help: consider further restricting `Self` - | -LL | fn transmute(&self, t: T) -> ::Assoc where Self: Sized; - | +++++++++++++++++ - -error[E0271]: type mismatch resolving `>::Assoc == Self` - --> $DIR/ice-generics-of-crate-root-152335.rs:21:30 - | -LL | trait Foo: Super - | ------------------------------------------------ - | | | - | | found type parameter - | expected type parameter -... -LL | ::Assoc: Super, - | ^^^^^ expected type parameter `Self`, found type parameter `T` - | - = note: expected type parameter `Self` - found type parameter `T` - = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound - = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 - | -LL | impl> Mirror for T {} - | --------- ^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/ice-generics-of-crate-root-152335.rs:21:30 - | -LL | ::Assoc: Super, - | ^^^^^ doesn't have a size known at compile-time - | -note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:38:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -230,7 +145,7 @@ help: consider further restricting `Self` LL | fn transmute(&self, t: T) -> ::Assoc where Self: Sized; | +++++++++++++++++ -error: aborting due to 14 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0038, E0046, E0271, E0277, E0405, E0601. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/errors/span-format_args-issue-140578.stderr b/tests/ui/errors/span-format_args-issue-140578.stderr index b5394b6c33afc..c4a2911d3fb07 100644 --- a/tests/ui/errors/span-format_args-issue-140578.stderr +++ b/tests/ui/errors/span-format_args-issue-140578.stderr @@ -2,31 +2,57 @@ error[E0282]: type annotations needed --> $DIR/span-format_args-issue-140578.rs:2:28 | LL | print!("{:?} {a} {a:?}", [], a = 1 + 1); - | ^^ cannot infer type + | ---- ^^ cannot infer type + | | + | required by this formatting parameter + | + = note: the type must also implement `Debug` + = note: required for `[_; 0]` to implement `Debug` error[E0282]: type annotations needed --> $DIR/span-format_args-issue-140578.rs:7:30 | LL | println!("{:?} {a} {a:?}", [], a = 1 + 1); - | ^^ cannot infer type + | ---- ^^ cannot infer type + | | + | required by this formatting parameter + | + = note: the type must also implement `Debug` + = note: required for `[_; 0]` to implement `Debug` error[E0282]: type annotations needed --> $DIR/span-format_args-issue-140578.rs:12:35 | LL | println!("{:?} {:?} {a} {a:?}", [], [], a = 1 + 1); - | ^^ cannot infer type + | ---- ^^ cannot infer type + | | + | required by this formatting parameter + | + = note: the type must also implement `Debug` + = note: required for `[_; 0]` to implement `Debug` error[E0282]: type annotations needed --> $DIR/span-format_args-issue-140578.rs:17:41 | LL | println!("{:?} {:?} {a} {a:?} {b:?}", [], [], a = 1 + 1, b = []); - | ^^ cannot infer type + | ---- ^^ cannot infer type + | | + | required by this formatting parameter + | + = note: the type must also implement `Debug` + = note: required for `[_; 0]` to implement `Debug` error[E0282]: type annotations needed --> $DIR/span-format_args-issue-140578.rs:26:9 | +LL | {:?} {:?} + | ---- required by this formatting parameter +... LL | [], | ^^ cannot infer type + | + = note: the type must also implement `Debug` + = note: required for `[_; 0]` to implement `Debug` error: aborting due to 5 previous errors diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr index 58ed71fad4a66..0dcc5f11d4861 100644 --- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr +++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr @@ -5,6 +5,7 @@ LL | cmp_eq | ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq` | = note: the type must implement `Scalar` + = note: cannot satisfy `::RefType<'_> == _` note: required by a bound in `cmp_eq` --> $DIR/ambig-hr-projection-issue-93340.rs:10:22 | diff --git a/tests/ui/generic-associated-types/bugs/issue-88382.stderr b/tests/ui/generic-associated-types/bugs/issue-88382.stderr index 0567e1c55a96f..8b6c8929dd608 100644 --- a/tests/ui/generic-associated-types/bugs/issue-88382.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-88382.stderr @@ -2,7 +2,9 @@ error[E0283]: type annotations needed --> $DIR/issue-88382.rs:26:40 | LL | do_something(SomeImplementation(), test); - | ^^^^ cannot infer type of the type parameter `I` declared on the function `test` + | ------------ ^^^^ cannot infer type of the type parameter `I` declared on the function `test` + | | + | required by a bound introduced by this call | = note: the type must implement `Iterable` help: the trait `Iterable` is implemented for `SomeImplementation` @@ -10,11 +12,17 @@ help: the trait `Iterable` is implemented for `SomeImplementation` | LL | impl Iterable for SomeImplementation { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: cannot satisfy `<_ as Iterable>::Iterator<'_> == std::iter::Empty` note: required by a bound in `test` --> $DIR/issue-88382.rs:29:16 | LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} | ^^^^^^^^ required by this bound in `test` +note: required by a bound in `do_something` + --> $DIR/issue-88382.rs:20:48 + | +LL | fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` help: consider specifying a concrete type for the type parameter `I` | LL | do_something(SomeImplementation(), test::); diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr index f136f5ffc82b4..0787aaa4263f4 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:41:5 + --> $DIR/false-positive-predicate-entailment-error.rs:40:5 | LL | / fn autobatch(self) -> impl Trait ... | @@ -20,7 +20,7 @@ LL | F: Callback + MyFn, | +++++++++++ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:41:5 + --> $DIR/false-positive-predicate-entailment-error.rs:40:5 | LL | / fn autobatch(self) -> impl Trait ... | @@ -41,11 +41,14 @@ help: consider further restricting type parameter `F` with trait `MyFn` LL | F: Callback + MyFn, | +++++++++++ -error[E0277]: the trait bound `F: Callback` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:48:12 +error[E0277]: the trait bound `F: MyFn` is not satisfied + --> $DIR/false-positive-predicate-entailment-error.rs:40:5 | -LL | F: Callback, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn` is not implemented for `F` +LL | / fn autobatch(self) -> impl Trait +... | +LL | | where +LL | | F: Callback, + | |_______________________________________^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` --> $DIR/false-positive-predicate-entailment-error.rs:19:21 @@ -54,24 +57,13 @@ LL | impl> Callback for F { | ------- ^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here -note: the requirement `F: Callback` appears on the `impl`'s method `autobatch` but not on the corresponding trait's method - --> $DIR/false-positive-predicate-entailment-error.rs:30:8 - | -LL | trait ChannelSender { - | ------------- in this trait -... -LL | fn autobatch(self) -> impl Trait - | ^^^^^^^^^ this trait's method doesn't have the requirement `F: Callback` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback + MyFn, | +++++++++++ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:41:30 - | -LL | fn autobatch(self) -> impl Trait - | ^^^^^^^^^^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` --> $DIR/false-positive-predicate-entailment-error.rs:19:21 @@ -81,11 +73,11 @@ LL | impl> Callback for F { | | | unsatisfied trait bound introduced here -error[E0277]: the trait bound `F: Callback` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:32:12 +error[E0277]: the trait bound `F: MyFn` is not satisfied + --> $DIR/false-positive-predicate-entailment-error.rs:40:30 | -LL | F: Callback; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn` is not implemented for `F` +LL | fn autobatch(self) -> impl Trait + | ^^^^^^^^^^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` --> $DIR/false-positive-predicate-entailment-error.rs:19:21 @@ -96,13 +88,10 @@ LL | impl> Callback for F { | unsatisfied trait bound introduced here error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:41:5 + --> $DIR/false-positive-predicate-entailment-error.rs:40:30 | -LL | / fn autobatch(self) -> impl Trait -... | -LL | | where -LL | | F: Callback, - | |_______________________________________^ the trait `MyFn` is not implemented for `F` +LL | fn autobatch(self) -> impl Trait + | ^^^^^^^^^^ the trait `MyFn` is not implemented for `F` | note: required for `F` to implement `Callback` --> $DIR/false-positive-predicate-entailment-error.rs:19:21 @@ -112,27 +101,7 @@ LL | impl> Callback for F { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider further restricting type parameter `F` with trait `MyFn` - | -LL | F: Callback + MyFn, - | +++++++++++ - -error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:48:12 - | -LL | F: Callback, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn` is not implemented for `F` - | -note: required by a bound in `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:15:20 - | -LL | trait Callback: MyFn { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Callback` -help: consider further restricting type parameter `F` with trait `MyFn` - | -LL | F: Callback + MyFn, - | +++++++++++ -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.next.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.next.stderr index 90569d9aecd4b..0787aaa4263f4 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.next.stderr +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:41:5 + --> $DIR/false-positive-predicate-entailment-error.rs:40:5 | LL | / fn autobatch(self) -> impl Trait ... | @@ -20,7 +20,7 @@ LL | F: Callback + MyFn, | +++++++++++ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:41:5 + --> $DIR/false-positive-predicate-entailment-error.rs:40:5 | LL | / fn autobatch(self) -> impl Trait ... | @@ -42,7 +42,7 @@ LL | F: Callback + MyFn, | +++++++++++ error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:41:5 + --> $DIR/false-positive-predicate-entailment-error.rs:40:5 | LL | / fn autobatch(self) -> impl Trait ... | @@ -74,7 +74,7 @@ LL | impl> Callback for F { | unsatisfied trait bound introduced here error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:41:30 + --> $DIR/false-positive-predicate-entailment-error.rs:40:30 | LL | fn autobatch(self) -> impl Trait | ^^^^^^^^^^ the trait `MyFn` is not implemented for `F` @@ -88,7 +88,7 @@ LL | impl> Callback for F { | unsatisfied trait bound introduced here error[E0277]: the trait bound `F: MyFn` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:41:30 + --> $DIR/false-positive-predicate-entailment-error.rs:40:30 | LL | fn autobatch(self) -> impl Trait | ^^^^^^^^^^ the trait `MyFn` is not implemented for `F` diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs index 044765233f56d..4778d8018d4c7 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs @@ -6,7 +6,7 @@ // But it regressed again as we switched back to be consistent with // the old solver. See #158643. -//[next]~^^^^^^^^ ERROR: the trait bound `F: MyFn` is not satisfied +//~^^^^^^^^ ERROR: the trait bound `F: MyFn` is not satisfied trait MyFn { type Output; @@ -30,7 +30,6 @@ trait ChannelSender { fn autobatch(self) -> impl Trait where F: Callback; - //[current]~^ ERROR the trait bound `F: Callback` is not satisfied } struct Sender; @@ -43,11 +42,9 @@ impl ChannelSender for Sender { //~| ERROR the trait bound `F: MyFn` is not satisfied //~| ERROR the trait bound `F: MyFn` is not satisfied //~| ERROR the trait bound `F: MyFn` is not satisfied - //[next]~| ERROR the trait bound `F: MyFn` is not satisfied + //~| ERROR the trait bound `F: MyFn` is not satisfied where F: Callback, - //[current]~^ ERROR the trait bound `F: MyFn` is not satisfied - //[current]~| ERROR the trait bound `F: Callback` is not satisfied { Thing } diff --git a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr index 8abced84ab86b..edef7a5e0a2c7 100644 --- a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr +++ b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr @@ -8,6 +8,7 @@ LL | loop {} | ------- return type was inferred to be `!` here | = note: the type must implement `Future` + = note: cannot satisfy `<_ as Future>::Output == ()` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index 52b63ae8177ea..a0cdc8ee89382 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -389,6 +389,7 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani where Args: std::marker::Tuple, F: Fn, A: Allocator, F: ?Sized; - impl Fn for SyncView where F: Sync, F: Fn, Args: std::marker::Tuple; + = note: cannot satisfy `<_ as FnOnce<()>>::Output == impl Debug` error: unconstrained opaque type --> $DIR/where-allowed.rs:122:16 diff --git a/tests/ui/inference/ambiguity-errors-single-diagnostic.rs b/tests/ui/inference/ambiguity-errors-single-diagnostic.rs new file mode 100644 index 0000000000000..7e8403b217ec4 --- /dev/null +++ b/tests/ui/inference/ambiguity-errors-single-diagnostic.rs @@ -0,0 +1,25 @@ +//! Ambiguity errors blaming the same inference variable are merged into a single +//! diagnostic that mentions every unsatisfied requirement, instead of only the +//! first one while the others get canceled as tainted-by-error duplicates. +//! +//! Regression test for . + +trait Trait {} +impl Trait for String {} +struct NotDefault; +impl Trait for NotDefault {} + +fn as_input(_: T) {} +fn constrained(_: T) {} + +fn two_bounds() { + as_input(Default::default()); + //~^ ERROR type annotations needed +} + +fn three_bounds() { + constrained(Default::default()); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/inference/ambiguity-errors-single-diagnostic.stderr b/tests/ui/inference/ambiguity-errors-single-diagnostic.stderr new file mode 100644 index 0000000000000..4488032717ce2 --- /dev/null +++ b/tests/ui/inference/ambiguity-errors-single-diagnostic.stderr @@ -0,0 +1,65 @@ +error[E0283]: type annotations needed + --> $DIR/ambiguity-errors-single-diagnostic.rs:16:5 + | +LL | as_input(Default::default()); + | ^^^^^^^^ ------------------ type must be known at this point + | | + | cannot infer type of the type parameter `T` declared on the function `as_input` + | + = note: the type must implement `Trait` +help: the following types implement trait `Trait` + --> $DIR/ambiguity-errors-single-diagnostic.rs:8:1 + | +LL | impl Trait for String {} + | ^^^^^^^^^^^^^^^^^^^^^ `String` +LL | struct NotDefault; +LL | impl Trait for NotDefault {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `NotDefault` + = note: the type must also implement `Default` +note: required by a bound in `as_input` + --> $DIR/ambiguity-errors-single-diagnostic.rs:12:16 + | +LL | fn as_input(_: T) {} + | ^^^^^ required by this bound in `as_input` +help: consider specifying a concrete type for the type parameter `T` + | +LL | as_input::(Default::default()); + | ++++++++++++++ + +error[E0283]: type annotations needed + --> $DIR/ambiguity-errors-single-diagnostic.rs:21:5 + | +LL | constrained(Default::default()); + | ^^^^^^^^^^^ ------------------ type must be known at this point + | | + | cannot infer type of the type parameter `T` declared on the function `constrained` + | + = note: the type must implement `Trait` +help: the following types implement trait `Trait` + --> $DIR/ambiguity-errors-single-diagnostic.rs:8:1 + | +LL | impl Trait for String {} + | ^^^^^^^^^^^^^^^^^^^^^ `String` +LL | struct NotDefault; +LL | impl Trait for NotDefault {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `NotDefault` + = note: the type must also implement `Clone` + = note: the type must also implement `Default` +note: required by a bound in `constrained` + --> $DIR/ambiguity-errors-single-diagnostic.rs:13:19 + | +LL | fn constrained(_: T) {} + | ^^^^^ required by this bound in `constrained` +note: required by a bound in `constrained` + --> $DIR/ambiguity-errors-single-diagnostic.rs:13:27 + | +LL | fn constrained(_: T) {} + | ^^^^^ required by this bound in `constrained` +help: consider specifying a concrete type for the type parameter `T` + | +LL | constrained::(Default::default()); + | ++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/issue-12028.stderr b/tests/ui/inference/issue-12028.stderr index 0d8ef1c938d4c..92cfd85d96f85 100644 --- a/tests/ui/inference/issue-12028.stderr +++ b/tests/ui/inference/issue-12028.stderr @@ -5,6 +5,14 @@ LL | self.input_stream(&mut stream); | ^^^^^^^^^^^^ | = note: cannot satisfy `<_ as StreamHasher>::S == ::S` + = note: the type must also implement `StreamHasher` +note: required by a bound in `StreamHash::input_stream` + --> $DIR/issue-12028.rs:20:21 + | +LL | trait StreamHash: Hash { + | ^^^^^^^^^^^^ required by this bound in `StreamHash::input_stream` +LL | fn input_stream(&self, stream: &mut H::S); + | ------------ required by a bound in this associated function help: try using a fully qualified path to specify the expected types | LL - self.input_stream(&mut stream); diff --git a/tests/ui/inference/issue-70082.stderr b/tests/ui/inference/issue-70082.stderr index 926ecff4a4fb5..5dc2311272e67 100644 --- a/tests/ui/inference/issue-70082.stderr +++ b/tests/ui/inference/issue-70082.stderr @@ -7,6 +7,9 @@ LL | let y: f64 = 0.01f64 * 1i16.into(); | type must be known at this point | = note: cannot satisfy `>::Output == f64` + = note: multiple `impl`s satisfying `f64: Mul<_>` found in the `core` crate: + - impl Mul for f64; + - impl Mul<&f64> for f64; help: try using a fully qualified path to specify the expected types | LL - let y: f64 = 0.01f64 * 1i16.into(); diff --git a/tests/ui/inference/issue-71584.stderr b/tests/ui/inference/issue-71584.stderr index 4bbfef6c44afa..1439ae6a51583 100644 --- a/tests/ui/inference/issue-71584.stderr +++ b/tests/ui/inference/issue-71584.stderr @@ -7,6 +7,10 @@ LL | d = d % n.into(); | type must be known at this point | = note: cannot satisfy `>::Output == u64` + = note: multiple `impl`s satisfying `u64: Rem<_>` found in the `core` crate: + - impl Rem for u64; + - impl Rem<&u64> for u64; + - impl Rem> for u64; help: try using a fully qualified path to specify the expected types | LL - d = d % n.into(); diff --git a/tests/ui/inference/issue-71732.stderr b/tests/ui/inference/issue-71732.stderr index 3b46a24e01088..04be1ce6c07f4 100644 --- a/tests/ui/inference/issue-71732.stderr +++ b/tests/ui/inference/issue-71732.stderr @@ -10,6 +10,12 @@ LL | .get(&"key".into()) - impl Borrow for String; - impl Borrow for T where T: ?Sized; + = note: the type must also implement `Hash` + = note: the type must also implement `Eq` +note: required by a bound in `HashMap::::get` + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL +note: required by a bound in `HashMap::::get` + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL note: required by a bound in `HashMap::::get` --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL help: consider specifying a concrete type for the type parameter `Q` diff --git a/tests/ui/inference/issue-80816.rs b/tests/ui/inference/issue-80816.rs index 4d319b44987e2..e5aae3abcb973 100644 --- a/tests/ui/inference/issue-80816.rs +++ b/tests/ui/inference/issue-80816.rs @@ -49,6 +49,7 @@ pub fn foo() { let s: Arc>> = unimplemented!(); let guard: Guard> = s.load(); //~^ ERROR: type annotations needed + //~| NOTE: cannot satisfy `> as Access<_>>::Guard == Guard>` //~| HELP: try using a fully qualified path to specify the expected types } diff --git a/tests/ui/inference/issue-80816.stderr b/tests/ui/inference/issue-80816.stderr index bca7cd4c3adbb..7230fd042df0f 100644 --- a/tests/ui/inference/issue-80816.stderr +++ b/tests/ui/inference/issue-80816.stderr @@ -12,6 +12,7 @@ LL | impl Access for ArcSwapAny { ... LL | impl Access for ArcSwapAny> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: cannot satisfy `> as Access<_>>::Guard == Guard>` note: required for `Arc>>` to implement `Access<_>` --> $DIR/issue-80816.rs:31:45 | diff --git a/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr b/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr index ff668f88d4d15..14d671f80e095 100644 --- a/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr +++ b/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/issue-107745-avoid-expr-from-macro-expansion.rs:17:22 | LL | println!("{:?}", []); - | ^^ cannot infer type + | ---- ^^ cannot infer type + | | + | required by this formatting parameter + | + = note: the type must also implement `Debug` + = note: required for `[_; 0]` to implement `Debug` error: aborting due to 1 previous error diff --git a/tests/ui/inference/need_type_info/single-type-generic-suggestion.stderr b/tests/ui/inference/need_type_info/single-type-generic-suggestion.stderr index fe696847eab7a..d1dcafcbc1d4d 100644 --- a/tests/ui/inference/need_type_info/single-type-generic-suggestion.stderr +++ b/tests/ui/inference/need_type_info/single-type-generic-suggestion.stderr @@ -5,6 +5,9 @@ LL | "".parse(); | ^^^^^ cannot infer type of the type parameter `F` declared on the method `parse` | = note: cannot satisfy `<_ as FromStr>::Err == _` + = note: the type must also implement `FromStr` +note: required by a bound in `core::str::::parse` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL help: consider specifying a concrete type for the type parameter `F` | LL | "".parse::(); diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs index ab3bf619f83b2..d770208668986 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs @@ -5,8 +5,6 @@ use std::future::Future; async fn wrapper(f: F) //~^ ERROR: expected an `FnOnce(&'a mut i32)` closure, found `i32` -//~| ERROR: expected an `FnOnce(&'a mut i32)` closure, found `i32` -//~| ERROR: expected an `FnOnce(&'a mut i32)` closure, found `i32` where F:, for<'a> >::Output: Future + 'a, diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr index 7a825b93461c0..96059302fd0b2 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr @@ -2,30 +2,14 @@ error[E0277]: expected an `FnOnce(&'a mut i32)` closure, found `i32` --> $DIR/issue-76168-hr-outlives-3.rs:6:1 | LL | / async fn wrapper(f: F) -... | +LL | | +LL | | where LL | | F:, LL | | for<'a> >::Output: Future + 'a, | |______________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` | = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` -error[E0277]: expected an `FnOnce(&'a mut i32)` closure, found `i32` - --> $DIR/issue-76168-hr-outlives-3.rs:6:26 - | -LL | async fn wrapper(f: F) - | ^ expected an `FnOnce(&'a mut i32)` closure, found `i32` - | - = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` - -error[E0277]: expected an `FnOnce(&'a mut i32)` closure, found `i32` - --> $DIR/issue-76168-hr-outlives-3.rs:6:26 - | -LL | async fn wrapper(f: F) - | ^ expected an `FnOnce(&'a mut i32)` closure, found `i32` - | - = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr index 22f3a258e6986..429c4edcad339 100644 --- a/tests/ui/traits/issue-77982.stderr +++ b/tests/ui/traits/issue-77982.stderr @@ -10,12 +10,28 @@ LL | opts.get(opt.as_ref()); - impl Borrow for String; - impl Borrow for T where T: ?Sized; + = note: the type must also implement `Hash` + = note: the type must also implement `Eq` +note: required by a bound in `HashMap::::get` + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL +note: required by a bound in `HashMap::::get` + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL note: required by a bound in `HashMap::::get` --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL help: consider specifying a concrete type for the type parameter `Q` | LL | opts.get::(opt.as_ref()); | ++++++++++++++ +help: consider removing this method call, as the receiver has type `String` and `String: Hash` trivially holds + | +LL - opts.get(opt.as_ref()); +LL + opts.get(opt); + | +help: consider removing this method call, as the receiver has type `String` and `String: Eq` trivially holds + | +LL - opts.get(opt.as_ref()); +LL + opts.get(opt); + | error[E0283]: type annotations needed --> $DIR/issue-77982.rs:11:10 diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index 7c3985f30cae9..b0d72f8f4706b 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -20,7 +20,7 @@ trait Foo { impl Foo for () { type Item = String where String: Copy; - //~^ ERROR overflow evaluating the requirement `String: Copy` + //~^ ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275] } diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index d82c5016eeaca..ffdf5c294ff64 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -4,19 +4,11 @@ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` LL | type Item = String where String: Copy; | ^^^^^^^^^ -error[E0275]: overflow evaluating the requirement `String: Copy` - --> $DIR/alias-bound-unsound.rs:22:38 +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` + --> $DIR/alias-bound-unsound.rs:22:17 | LL | type Item = String where String: Copy; - | ^^^^ - | -note: the requirement `String: Copy` appears on the `impl`'s associated type `Item` but not on the corresponding trait's associated type - --> $DIR/alias-bound-unsound.rs:12:10 - | -LL | trait Foo { - | --- in this trait -LL | type Item: Copy - | ^^^^ this trait's associated type doesn't have the requirement `String: Copy` + | ^^^^^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == String` --> $DIR/alias-bound-unsound.rs:29:22 diff --git a/tests/ui/traits/next-solver/const-alias-in-outlive-clause.rs b/tests/ui/traits/next-solver/const-alias-in-outlive-clause.rs new file mode 100644 index 0000000000000..4873fa02c388f --- /dev/null +++ b/tests/ui/traits/next-solver/const-alias-in-outlive-clause.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Previously we resolve regions in elaborated param env when normalizing +// param env. +// Since elaborated param env is unnormalized, we got non rigid type outlive +// clause in lexical region solving. +// Type aliases didn't have this problem because we set them to rigid in +// elaborated env as a hack. + +fn foo() +where + [T; 1 + 1]: 'static, +{} + +fn main() {} diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs index cb37d2c457a42..f7a9ce768bcfe 100644 --- a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs @@ -42,13 +42,10 @@ fn generic() //~^ ERROR the trait bound `Foo: Bound` is not satisfied where >::Assoc: Bound, - //~^ ERROR overflow evaluating the requirement `>::Assoc: Bound` - //~| ERROR overflow evaluating whether `>::Assoc` is well-formed { // Requires proving `Foo: Bound` by normalizing // `>::Assoc` to `Foo`. impls_bound::(); - //~^ ERROR overflow evaluating the requirement `Foo: Bound` } fn main() { // Requires proving `>::Assoc: Bound`. diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr index 7aeff2d06dabb..747b5c6720e83 100644 --- a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr @@ -25,31 +25,6 @@ LL | impl Trait for T { | | | unsatisfied trait bound introduced here -error[E0275]: overflow evaluating the requirement `>::Assoc: Bound` - --> $DIR/normalizes-to-is-not-productive.rs:44:31 - | -LL | >::Assoc: Bound, - | ^^^^^ - -error[E0275]: overflow evaluating whether `>::Assoc` is well-formed - --> $DIR/normalizes-to-is-not-productive.rs:44:31 - | -LL | >::Assoc: Bound, - | ^^^^^ - -error[E0275]: overflow evaluating the requirement `Foo: Bound` - --> $DIR/normalizes-to-is-not-productive.rs:50:19 - | -LL | impls_bound::(); - | ^^^ - | -note: required by a bound in `impls_bound` - --> $DIR/normalizes-to-is-not-productive.rs:28:19 - | -LL | fn impls_bound() { - | ^^^^^ required by this bound in `impls_bound` - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0275, E0277. -For more information about an error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/param-env-normalization-fallback.next.stderr b/tests/ui/traits/next-solver/param-env-normalization-fallback.next.stderr new file mode 100644 index 0000000000000..8028c4d5415f3 --- /dev/null +++ b/tests/ui/traits/next-solver/param-env-normalization-fallback.next.stderr @@ -0,0 +1,42 @@ +error[E0277]: the trait bound `Indir: Trait1` is not satisfied + --> $DIR/param-env-normalization-fallback.rs:21:1 + | +LL | / impl Trait2 for T +LL | | +LL | | where +LL | | T: Trait1, +LL | | T::Assoc1: 'static, +LL | | T: Trait1::Assoc1>, + | |__________________________________________________^ unsatisfied trait bound + | +help: the trait `Trait1` is not implemented for `Indir` + --> $DIR/param-env-normalization-fallback.rs:15:1 + | +LL | struct Indir; + | ^^^^^^^^^^^^ +help: this trait has no implementations, consider adding one + --> $DIR/param-env-normalization-fallback.rs:11:1 + | +LL | trait Trait1 { + | ^^^^^^^^^^^^ + +error[E0277]: the trait bound `Indir: Trait1` is not satisfied + --> $DIR/param-env-normalization-fallback.rs:28:5 + | +LL | type Assoc2 = (); + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `Trait1` is not implemented for `Indir` + --> $DIR/param-env-normalization-fallback.rs:15:1 + | +LL | struct Indir; + | ^^^^^^^^^^^^ +help: this trait has no implementations, consider adding one + --> $DIR/param-env-normalization-fallback.rs:11:1 + | +LL | trait Trait1 { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/param-env-normalization-fallback.old.stderr b/tests/ui/traits/next-solver/param-env-normalization-fallback.old.stderr new file mode 100644 index 0000000000000..8028c4d5415f3 --- /dev/null +++ b/tests/ui/traits/next-solver/param-env-normalization-fallback.old.stderr @@ -0,0 +1,42 @@ +error[E0277]: the trait bound `Indir: Trait1` is not satisfied + --> $DIR/param-env-normalization-fallback.rs:21:1 + | +LL | / impl Trait2 for T +LL | | +LL | | where +LL | | T: Trait1, +LL | | T::Assoc1: 'static, +LL | | T: Trait1::Assoc1>, + | |__________________________________________________^ unsatisfied trait bound + | +help: the trait `Trait1` is not implemented for `Indir` + --> $DIR/param-env-normalization-fallback.rs:15:1 + | +LL | struct Indir; + | ^^^^^^^^^^^^ +help: this trait has no implementations, consider adding one + --> $DIR/param-env-normalization-fallback.rs:11:1 + | +LL | trait Trait1 { + | ^^^^^^^^^^^^ + +error[E0277]: the trait bound `Indir: Trait1` is not satisfied + --> $DIR/param-env-normalization-fallback.rs:28:5 + | +LL | type Assoc2 = (); + | ^^^^^^^^^^^ unsatisfied trait bound + | +help: the trait `Trait1` is not implemented for `Indir` + --> $DIR/param-env-normalization-fallback.rs:15:1 + | +LL | struct Indir; + | ^^^^^^^^^^^^ +help: this trait has no implementations, consider adding one + --> $DIR/param-env-normalization-fallback.rs:11:1 + | +LL | trait Trait1 { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/param-env-normalization-fallback.rs b/tests/ui/traits/next-solver/param-env-normalization-fallback.rs new file mode 100644 index 0000000000000..aa24df4984ae6 --- /dev/null +++ b/tests/ui/traits/next-solver/param-env-normalization-fallback.rs @@ -0,0 +1,32 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + +// Previously the fallback of param env normalization was elaborated param env +// when the normalization failed. +// The elaborated param env is entirely unnormalized which causes problems for +// places where we expect normalized param env, e.g. in lexical region solving. +// +// Now we map non-rigid aliases and unresolved infer vars to `Ty/Const/Region::Error`. + +trait Trait1 { + type Assoc1; +} + +struct Indir; + +trait Trait2 { + type Assoc2; +} + +impl Trait2 for T +//~^ ERROR: the trait bound `Indir: Trait1` is not satisfied +where + T: Trait1, + T::Assoc1: 'static, + T: Trait1::Assoc1>, +{ + type Assoc2 = (); + //~^ ERROR: the trait bound `Indir: Trait1` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/unexpected-pointer-deref-issue-154568.stderr b/tests/ui/traits/next-solver/unexpected-pointer-deref-issue-154568.stderr index 3c5a00744a636..90cd6a36d9c0b 100644 --- a/tests/ui/traits/next-solver/unexpected-pointer-deref-issue-154568.stderr +++ b/tests/ui/traits/next-solver/unexpected-pointer-deref-issue-154568.stderr @@ -5,6 +5,7 @@ LL | let handshake = Handshake(callback.0.clone()); | ^^^^^^^^^ ----------------------------- type must be known at this point | = note: the type must implement `Role` + = note: cannot satisfy `<_ as Role>::Inner == ()` note: required by a bound in `Handshake` --> $DIR/unexpected-pointer-deref-issue-154568.rs:9:21 | diff --git a/tests/ui/traits/next-solver/well-formed-in-relate.stderr b/tests/ui/traits/next-solver/well-formed-in-relate.stderr index dbe8a656812a5..d1113d0a3e6b6 100644 --- a/tests/ui/traits/next-solver/well-formed-in-relate.stderr +++ b/tests/ui/traits/next-solver/well-formed-in-relate.stderr @@ -14,11 +14,17 @@ LL | x = unconstrained_map(); where Args: std::marker::Tuple, F: Fn, A: Allocator, F: ?Sized; - impl Fn for SyncView where F: Sync, F: Fn, Args: std::marker::Tuple; + = note: cannot satisfy `<_ as FnOnce<()>>::Output == _` note: required by a bound in `unconstrained_map` --> $DIR/well-formed-in-relate.rs:21:25 | LL | fn unconstrained_map U, U>() -> as Mirror>::Assoc { todo!() } | ^^^^^^^^^ required by this bound in `unconstrained_map` +note: required by a bound in `unconstrained_map` + --> $DIR/well-formed-in-relate.rs:21:33 + | +LL | fn unconstrained_map U, U>() -> as Mirror>::Assoc { todo!() } + | ^ required by this bound in `unconstrained_map` help: consider giving `x` an explicit type, where the type for type parameter `T` is specified | LL | let x: Map; diff --git a/tests/ui/traits/normalize/deep-norm-pending.rs b/tests/ui/traits/normalize/deep-norm-pending.rs index 9b1ec522bef31..9f05df9ea5a70 100644 --- a/tests/ui/traits/normalize/deep-norm-pending.rs +++ b/tests/ui/traits/normalize/deep-norm-pending.rs @@ -4,21 +4,17 @@ trait Foo { trait Bar { fn method() -> impl Sized; - //~^ ERROR the trait bound `T: Foo` is not satisfied } impl Bar for T -//~^ ERROR the trait bound `T: Bar` is not satisfied -//~| ERROR the trait bound `T: Foo` is not satisfied +//~^ ERROR the trait bound `T: Foo` is not satisfied where ::Assoc: Sized, - //~^ ERROR the trait bound `T: Foo` is not satisfied { fn method() {} //~^ ERROR the trait bound `T: Foo` is not satisfied //~| ERROR the trait bound `T: Foo` is not satisfied //~| ERROR the trait bound `T: Foo` is not satisfied //~| ERROR the trait bound `T: Foo` is not satisfied - //~| ERROR the trait bound `T: Foo` is not satisfied } fn main() {} diff --git a/tests/ui/traits/normalize/deep-norm-pending.stderr b/tests/ui/traits/normalize/deep-norm-pending.stderr index f2b59748ced90..8fa70e342b26e 100644 --- a/tests/ui/traits/normalize/deep-norm-pending.stderr +++ b/tests/ui/traits/normalize/deep-norm-pending.stderr @@ -1,9 +1,8 @@ error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/deep-norm-pending.rs:9:1 + --> $DIR/deep-norm-pending.rs:8:1 | LL | / impl Bar for T LL | | -LL | | LL | | where LL | | ::Assoc: Sized, | |_____________________________^ the trait `Foo` is not implemented for `T` @@ -14,7 +13,7 @@ LL | ::Assoc: Sized, T: Foo | ++++++ error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/deep-norm-pending.rs:16:5 + --> $DIR/deep-norm-pending.rs:13:5 | LL | fn method() {} | ^^^^^^^^^^^ the trait `Foo` is not implemented for `T` @@ -25,7 +24,7 @@ LL | ::Assoc: Sized, T: Foo | ++++++ error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/deep-norm-pending.rs:16:5 + --> $DIR/deep-norm-pending.rs:13:5 | LL | fn method() {} | ^^^^^^^^^^^ the trait `Foo` is not implemented for `T` @@ -37,26 +36,7 @@ LL | ::Assoc: Sized, T: Foo | ++++++ error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/deep-norm-pending.rs:16:5 - | -LL | fn method() {} - | ^^^^^^^^^^^ the trait `Foo` is not implemented for `T` - | -note: required for `T` to implement `Bar` - --> $DIR/deep-norm-pending.rs:9:9 - | -LL | impl Bar for T - | ^^^ ^ -... -LL | ::Assoc: Sized, - | ----- unsatisfied trait bound introduced here -help: consider further restricting type parameter `T` with trait `Foo` - | -LL | ::Assoc: Sized, T: Foo - | ++++++ - -error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/deep-norm-pending.rs:16:5 + --> $DIR/deep-norm-pending.rs:13:5 | LL | fn method() {} | ^^^^^^^^^^^ the trait `Foo` is not implemented for `T` @@ -68,45 +48,7 @@ LL | ::Assoc: Sized, T: Foo | ++++++ error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/deep-norm-pending.rs:6:20 - | -LL | fn method() -> impl Sized; - | ^^^^^^^^^^ the trait `Foo` is not implemented for `T` - | -note: required for `T` to implement `Bar` - --> $DIR/deep-norm-pending.rs:9:9 - | -LL | impl Bar for T - | ^^^ ^ -... -LL | ::Assoc: Sized, - | ----- unsatisfied trait bound introduced here -help: consider further restricting type parameter `T` with trait `Foo` - | -LL | ::Assoc: Sized, T: Foo - | ++++++ - -error[E0277]: the trait bound `T: Bar` is not satisfied - --> $DIR/deep-norm-pending.rs:9:17 - | -LL | impl Bar for T - | ^ the trait `Foo` is not implemented for `T` - | -note: required for `T` to implement `Bar` - --> $DIR/deep-norm-pending.rs:9:9 - | -LL | impl Bar for T - | ^^^ ^ -... -LL | ::Assoc: Sized, - | ----- unsatisfied trait bound introduced here -help: consider further restricting type parameter `T` with trait `Foo` - | -LL | ::Assoc: Sized, T: Foo - | ++++++ - -error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/deep-norm-pending.rs:16:5 + --> $DIR/deep-norm-pending.rs:13:5 | LL | fn method() {} | ^^^^^^^^^^^ the trait `Foo` is not implemented for `T` @@ -117,17 +59,6 @@ help: consider further restricting type parameter `T` with trait `Foo` LL | ::Assoc: Sized, T: Foo | ++++++ -error[E0277]: the trait bound `T: Foo` is not satisfied - --> $DIR/deep-norm-pending.rs:13:24 - | -LL | ::Assoc: Sized, - | ^^^^^ the trait `Foo` is not implemented for `T` - | -help: consider further restricting type parameter `T` with trait `Foo` - | -LL | ::Assoc: Sized, T: Foo - | ++++++ - -error: aborting due to 9 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/unhandled-crate-mod-issue-144888.rs b/tests/ui/traits/unhandled-crate-mod-issue-144888.rs index 779faae6688c8..8c9085ee80b35 100644 --- a/tests/ui/traits/unhandled-crate-mod-issue-144888.rs +++ b/tests/ui/traits/unhandled-crate-mod-issue-144888.rs @@ -12,10 +12,6 @@ trait Foo: Super //~| ERROR the size for values of type `Self` cannot be known at compilation time where ::Assoc: Clone, - //~^ ERROR type mismatch resolving - //~| ERROR the size for values of type `Self` cannot be known at compilation time - //~| ERROR type mismatch resolving - //~| ERROR the size for values of type `Self` cannot be known at compilation time { fn transmute(&self) {} //~^ ERROR type mismatch resolving diff --git a/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr b/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr index 9829dab3029bb..3208945a5b732 100644 --- a/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr +++ b/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `::Assoc == ()` - --> $DIR/unhandled-crate-mod-issue-144888.rs:20:5 + --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 | LL | fn transmute(&self) {} | ^^^^^^^^^^^^^^^^^^^ expected `()`, found type parameter `T` @@ -7,7 +7,7 @@ LL | fn transmute(&self) {} = note: expected unit type `()` found type parameter `T` note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 | LL | impl> Mirror for T {} | ---------- ^^^^^^ ^ @@ -15,13 +15,13 @@ LL | impl> Mirror for T {} | unsatisfied trait bound introduced here error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/unhandled-crate-mod-issue-144888.rs:20:5 + --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 | LL | fn transmute(&self) {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -37,7 +37,7 @@ LL | trait Foo: Super = note: expected unit type `()` found type parameter `T` note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 | LL | impl> Mirror for T {} | ---------- ^^^^^^ ^ @@ -51,44 +51,7 @@ LL | trait Foo: Super | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 - | -LL | impl> Mirror for T {} - | - ^^^^^^ ^ - | | - | unsatisfied trait bound implicitly introduced here -help: consider further restricting `Self` - | -LL | trait Foo: Super + Sized - | +++++++ - -error[E0271]: type mismatch resolving `::Assoc == ()` - --> $DIR/unhandled-crate-mod-issue-144888.rs:14:30 - | -LL | trait Foo: Super - | - found this type parameter -... -LL | ::Assoc: Clone, - | ^^^^^ expected `()`, found type parameter `T` - | - = note: expected unit type `()` - found type parameter `T` -note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 - | -LL | impl> Mirror for T {} - | ---------- ^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - -error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/unhandled-crate-mod-issue-144888.rs:14:30 - | -LL | ::Assoc: Clone, - | ^^^^^ doesn't have a size known at compile-time - | -note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -100,7 +63,7 @@ LL | trait Foo: Super + Sized | +++++++ error[E0046]: not all trait items implemented, missing: `Assoc` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:1 + --> $DIR/unhandled-crate-mod-issue-144888.rs:27:1 | LL | type Assoc; | ---------- `Assoc` from trait @@ -109,7 +72,7 @@ LL | impl> Mirror for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Assoc` in implementation error[E0271]: type mismatch resolving `::Assoc == ()` - --> $DIR/unhandled-crate-mod-issue-144888.rs:20:5 + --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 | LL | trait Foo: Super | - found this type parameter @@ -120,7 +83,7 @@ LL | fn transmute(&self) {} = note: expected unit type `()` found type parameter `T` note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 | LL | impl> Mirror for T {} | ---------- ^^^^^^ ^ @@ -128,51 +91,13 @@ LL | impl> Mirror for T {} | unsatisfied trait bound introduced here error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/unhandled-crate-mod-issue-144888.rs:20:5 + --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 | LL | fn transmute(&self) {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 - | -LL | impl> Mirror for T {} - | - ^^^^^^ ^ - | | - | unsatisfied trait bound implicitly introduced here -help: consider further restricting `Self` - | -LL | fn transmute(&self) where Self: Sized {} - | +++++++++++++++++ - -error[E0271]: type mismatch resolving `::Assoc == ()` - --> $DIR/unhandled-crate-mod-issue-144888.rs:14:30 - | -LL | trait Foo: Super - | - found this type parameter -... -LL | ::Assoc: Clone, - | ^^^^^ expected `()`, found type parameter `T` - | - = note: expected unit type `()` - found type parameter `T` -note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 - | -LL | impl> Mirror for T {} - | ---------- ^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/unhandled-crate-mod-issue-144888.rs:14:30 - | -LL | ::Assoc: Clone, - | ^^^^^ doesn't have a size known at compile-time - | -note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -183,7 +108,7 @@ help: consider further restricting `Self` LL | fn transmute(&self) where Self: Sized {} | +++++++++++++++++ -error: aborting due to 11 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0046, E0271, E0277. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/type-inference/index-expr-ambiguous-type.stderr b/tests/ui/type-inference/index-expr-ambiguous-type.stderr index 83de98d80cae6..1e2ea9ab32215 100644 --- a/tests/ui/type-inference/index-expr-ambiguous-type.stderr +++ b/tests/ui/type-inference/index-expr-ambiguous-type.stderr @@ -11,6 +11,9 @@ LL | let _foo = 0 + [1, 2, 3][bad_idx.into()]; | ^^^^ cannot infer type | = note: cannot satisfy `>::Output == _` + = note: multiple `impl`s satisfying `i32: Add<_>` found in the `core` crate: + - impl Add for i32; + - impl Add<&i32> for i32; error[E0283]: type annotations needed --> $DIR/index-expr-ambiguous-type.rs:21:34 @@ -41,6 +44,9 @@ LL | let _foo = 0u64 + [1i32, 2, 3][bad_idx.into()]; | ^ cannot infer type | = note: cannot satisfy `>::Output == _` + = note: multiple `impl`s satisfying `u64: Add<_>` found in the `core` crate: + - impl Add for u64; + - impl Add<&u64> for u64; error[E0284]: type annotations needed --> $DIR/index-expr-ambiguous-type.rs:44:38 @@ -49,6 +55,7 @@ LL | let _foo = 1u32 << [0u8][bad_idx.into()]; | ^^^^ cannot infer type | = note: cannot satisfy `>::Output == _` + = note: cannot satisfy `u32: Shl<_>` error[E0283]: type annotations needed --> $DIR/index-expr-ambiguous-type.rs:50:45 diff --git a/tests/ui/type-inference/or_else-multiple-type-params.stderr b/tests/ui/type-inference/or_else-multiple-type-params.stderr index 9bcd07f8bf164..ea64b91b726d7 100644 --- a/tests/ui/type-inference/or_else-multiple-type-params.stderr +++ b/tests/ui/type-inference/or_else-multiple-type-params.stderr @@ -3,7 +3,13 @@ error[E0282]: type annotations needed for `Result` | LL | .or_else(|err| { | ^^^^^ +LL | panic!("oh no: {:?}", err); +LL | }).unwrap(); + | ------ required by a bound introduced by this call | + = note: the type must also implement `Debug` +note: required by a bound in `Result::::unwrap` + --> $SRC_DIR/core/src/result.rs:LL:COL help: try giving this closure an explicit return type | LL | .or_else(|err| -> Result<_, F> { diff --git a/tests/ui/type-inference/panic-with-unspecified-type.stderr b/tests/ui/type-inference/panic-with-unspecified-type.stderr index 99c6e83ef3225..99949d4901a4e 100644 --- a/tests/ui/type-inference/panic-with-unspecified-type.stderr +++ b/tests/ui/type-inference/panic-with-unspecified-type.stderr @@ -6,8 +6,13 @@ LL | panic!(std::default::Default::default()); | | | | | cannot infer type | required by a bound introduced by this call + | required by a bound introduced by this call | = note: the type must implement `Any` + = note: the type must also implement `Send` + = note: the type must also implement `Default` +note: required by a bound in `std::rt::begin_panic` + --> $SRC_DIR/std/src/panicking.rs:LL:COL note: required by a bound in `std::rt::begin_panic` --> $SRC_DIR/std/src/panicking.rs:LL:COL diff --git a/tests/ui/typeck/issue-116864.current.stderr b/tests/ui/typeck/issue-116864.current.stderr index b3fbf6b0e570f..ae38a6d3439de 100644 --- a/tests/ui/typeck/issue-116864.current.stderr +++ b/tests/ui/typeck/issue-116864.current.stderr @@ -2,7 +2,8 @@ error[E0277]: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMu --> $DIR/issue-116864.rs:28:1 | LL | / async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) -... | +LL | | +LL | | LL | | where LL | | BAZ: Baz, | |__________________________^ expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` @@ -18,91 +19,6 @@ LL | where LL | F: FnMut(P) -> FUT, | --------------- unsatisfied trait bound introduced here -error[E0277]: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` - --> $DIR/issue-116864.rs:28:81 - | -LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) - | ^ expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` - | - = note: expected a closure with signature `for<'any> fn(&'any i32)` - found a closure with signature `fn(&::Param)` -note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` - --> $DIR/issue-116864.rs:20:20 - | -LL | impl FnMutFut for F - | ^^^^^^^^^^^^^^ ^ -LL | where -LL | F: FnMut(P) -> FUT, - | --------------- unsatisfied trait bound introduced here -note: required by a bound in `foo` - --> $DIR/issue-116864.rs:28:40 - | -LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` - -error[E0277]: expected an `FnMut(&i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` - --> $DIR/issue-116864.rs:36:5 - | -LL | cb(&1i32).await; - | ^^^^^^^^^ expected an `FnMut(&i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` - | - = note: expected a closure with signature `fn(&i32)` - found a closure with signature `fn(&::Param)` -note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `FnMutFut<&i32, ()>` - --> $DIR/issue-116864.rs:20:20 - | -LL | impl FnMutFut for F - | ^^^^^^^^^^^^^^ ^ -LL | where -LL | F: FnMut(P) -> FUT, - | --------------- unsatisfied trait bound introduced here - -error[E0308]: mismatched types - --> $DIR/issue-116864.rs:36:8 - | -LL | cb(&1i32).await; - | -- ^^^^^ expected `&::Param`, found `&i32` - | | - | arguments to this function are incorrect - | - = note: expected reference `&::Param` - found reference `&i32` - = help: consider constraining the associated type `::Param` to `i32` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -note: type parameter defined here - --> $DIR/issue-116864.rs:28:35 - | -LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: call `Into::into` on this expression to convert `&i32` into `&::Param` - | -LL | cb((&1i32).into()).await; - | + ++++++++ - -error[E0277]: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` - --> $DIR/issue-116864.rs:28:81 - | -LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) - | ^ expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` - | - = note: expected a closure with signature `for<'any> fn(&'any i32)` - found a closure with signature `fn(&::Param)` -note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` - --> $DIR/issue-116864.rs:20:20 - | -LL | impl FnMutFut for F - | ^^^^^^^^^^^^^^ ^ -LL | where -LL | F: FnMut(P) -> FUT, - | --------------- unsatisfied trait bound introduced here -note: required by a bound in `foo` - --> $DIR/issue-116864.rs:28:40 - | -LL | async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 5 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-116864.next.stderr b/tests/ui/typeck/issue-116864.next.stderr index e7d951dcff260..c53410b1a1ec6 100644 --- a/tests/ui/typeck/issue-116864.next.stderr +++ b/tests/ui/typeck/issue-116864.next.stderr @@ -2,7 +2,8 @@ error[E0277]: expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnM --> $DIR/issue-116864.rs:28:1 | LL | / async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) -... | +LL | | +LL | | LL | | where LL | | BAZ: Baz, | |__________________________^ expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` diff --git a/tests/ui/typeck/issue-116864.rs b/tests/ui/typeck/issue-116864.rs index 568b56bfc44ee..427afe1784e92 100644 --- a/tests/ui/typeck/issue-116864.rs +++ b/tests/ui/typeck/issue-116864.rs @@ -28,14 +28,10 @@ where async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) //[next]~^ ERROR: expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` //[current]~^^ ERROR: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` -//[current]~| ERROR: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` -//[current]~| ERROR: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` where BAZ: Baz, { cb(&1i32).await; - //[current]~^ ERROR: expected an `FnMut(&i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` - //[current]~| ERROR: mismatched types } fn main() { diff --git a/tests/ui/typeck/type-inference-for-associated-types-69683.rs b/tests/ui/typeck/type-inference-for-associated-types-69683.rs index f18adcae23b05..756a0112710d9 100644 --- a/tests/ui/typeck/type-inference-for-associated-types-69683.rs +++ b/tests/ui/typeck/type-inference-for-associated-types-69683.rs @@ -29,6 +29,5 @@ fn main() { let b: [u8; 3] = [0u8; 3]; 0u16.foo(b); //~ ERROR type annotations needed - //~^ ERROR type annotations needed //>::foo(0u16, b); } diff --git a/tests/ui/typeck/type-inference-for-associated-types-69683.stderr b/tests/ui/typeck/type-inference-for-associated-types-69683.stderr index 5d49d442c55d0..46ddd4556e96f 100644 --- a/tests/ui/typeck/type-inference-for-associated-types-69683.stderr +++ b/tests/ui/typeck/type-inference-for-associated-types-69683.stderr @@ -5,18 +5,6 @@ LL | 0u16.foo(b); | ^^^ | = note: cannot satisfy `>::Array == [u8; 3]` -help: try using a fully qualified path to specify the expected types - | -LL - 0u16.foo(b); -LL + >::foo(0u16, b); - | - -error[E0283]: type annotations needed - --> $DIR/type-inference-for-associated-types-69683.rs:31:10 - | -LL | 0u16.foo(b); - | ^^^ - | note: multiple `impl`s satisfying `u8: Element<_>` found --> $DIR/type-inference-for-associated-types-69683.rs:6:1 | @@ -39,7 +27,6 @@ LL - 0u16.foo(b); LL + >::foo(0u16, b); | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0283, E0284. -For more information about an error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.rs b/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.rs new file mode 100644 index 0000000000000..47e3fa477ea69 --- /dev/null +++ b/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.rs @@ -0,0 +1,20 @@ +// Regression test for https://github.com/rust-lang/rust/issues/148630 +// +// We previously ran into ICE in wfcheck diagnostics code. +// After replacing unconstained infers and non-rigid aliases with `Ty/Const/Region::Error` +// in param env normalization, this no longer ICEs. + +#![feature(unboxed_closures)] + +trait Tr {} +trait Foo { + fn foo() -> impl Sized + //~^ ERROR: expected an `FnOnce<&'a i32>` closure, found `()` + //~| ERROR: expected an `FnOnce<&'a i32>` closure, found `()` + where + for<'a> <() as FnOnce<&'a i32>>::Output: Tr, + { + } +} + +fn main() {} diff --git a/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.stderr b/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.stderr new file mode 100644 index 0000000000000..7457f76eb39f6 --- /dev/null +++ b/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.stderr @@ -0,0 +1,23 @@ +error[E0277]: expected an `FnOnce<&'a i32>` closure, found `()` + --> $DIR/closure-trait-ice-in-wfcheck-diagnostics.rs:11:17 + | +LL | fn foo() -> impl Sized + | ^^^^^^^^^^ expected an `FnOnce<&'a i32>` closure, found `()` + | + = help: the trait `for<'a> FnOnce<&'a i32>` is not implemented for `()` + +error[E0277]: expected an `FnOnce<&'a i32>` closure, found `()` + --> $DIR/closure-trait-ice-in-wfcheck-diagnostics.rs:11:5 + | +LL | / fn foo() -> impl Sized +LL | | +LL | | +LL | | where +LL | | for<'a> <() as FnOnce<&'a i32>>::Output: Tr, + | |____________________________________________________^ expected an `FnOnce<&'a i32>` closure, found `()` + | + = help: the trait `for<'a> FnOnce<&'a i32>` is not implemented for `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`.