diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a2e94492f8c23..514d903c14d8f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1893,6 +1893,7 @@ symbols! { three_way_compare, thumb2, thumb_mode: "thumb-mode", + time, tmm_reg, to_owned_method, to_string, diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 137850f31d31e..69bc26b00d9b2 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -446,6 +446,8 @@ trait_selection_type_annotations_needed = {$source_kind -> } .label = type must be known at this point +trait_selection_type_annotations_needed_error_time = this is an inference error on `time` caused by a change in Rust 1.80.0; update `time` to version `>=0.3.36` + trait_selection_types_declared_different = these two types are declared with different lifetimes... trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index f6dd7898fb28e..c5060936a65cf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -6,7 +6,7 @@ use rustc_errors::codes::*; use rustc_errors::{Diag, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource}; use rustc_middle::bug; @@ -18,7 +18,7 @@ use rustc_middle::ty::{ TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, }; use rustc_span::symbol::{sym, Ident}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; use crate::error_reporting::TypeErrCtxt; use crate::errors::{ @@ -384,6 +384,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label, was_written: None, path: Default::default(), + time_version: None, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -577,6 +578,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } + + let time_version = self.detect_old_time_crate_version(failure_span, &mut infer_subdiags); + match error_code { TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired { span, @@ -588,6 +592,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label: None, was_written: path.as_ref().map(|_| ()), path: path.unwrap_or_default(), + time_version, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -613,6 +618,57 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }), } } + + /// Detect the inference regression on crate `time` <= 0.3.35 and emit a more targeted error. + /// + // FIXME: we should figure out a more generic version of doing this, ideally in cargo itself. + fn detect_old_time_crate_version( + &self, + span: Option, + /// We will clear the non-actionable suggestion from the error to reduce noise. + infer_subdiags: &mut Vec>, + ) -> Option<()> { + if self.infcx.tcx.crate_name(LOCAL_CRATE) != sym::time { + // Only relevant when building the `time` crate. + return None; + } + let Some(span) = span else { return None }; + let FileName::Real(file) = self.infcx.tcx.sess.source_map().span_to_filename(span) else { + return None; + }; + let path = file.local_path_if_available(); + let mut components = path.components(); + // We will take the filename of the error and see if it is of the form + // `.../registry/src/index.crates.io-.../time-0...`, in order to detect the specific case + // we care about. + while let Some(component) = components.next() { + let std::path::Component::Normal(component) = component else { + continue; + }; + if component == "registry" + && let Some(next) = components.next() + && let std::path::Component::Normal(next) = next + && next == "src" + && let Some(next) = components.next() + && let std::path::Component::Normal(next) = next + && next.to_string_lossy().starts_with("index.") + && let Some(next) = components.next() + && let std::path::Component::Normal(next) = next + && let next = next.to_string_lossy() + && next.starts_with("time-0.") + && let Some(version) = next.split('-').skip(1).next() + && let mut segments = version.split('.') + && let Some(major) = segments.next() + && major == "0" + && let Some(minor) = segments.next() + && minor == "3" + { + infer_subdiags.clear(); + return Some(()); + } + } + None + } } #[derive(Debug)] diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 78f1f7d9b9b59..c375aa453b846 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -205,6 +205,8 @@ pub struct AnnotationRequired<'a> { #[note(trait_selection_full_type_written)] pub was_written: Option<()>, pub path: PathBuf, + #[note(trait_selection_type_annotations_needed_error_time)] + pub time_version: Option<()>, } // Copy of `AnnotationRequired` for E0283