Emit specific message for time<0.3.35 inference failure

```
error[E0282]: type annotations needed for `Box<_>`
  --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/time-0.3.34/src/format_description/parse/mod.rs:83:9
   |
83 |     let items = format_items
   |         ^^^^^
...
86 |     Ok(items.into())
   |              ---- type must be known at this point
   |
   = note: this is an inference error on crate `time` caused by a change in Rust 1.80.0; update `time` to version `>=0.3.35`
```

Partially address #127343.
This commit is contained in:
Esteban Küber 2024-08-21 03:17:47 +00:00
parent 100fde5246
commit b013a3ddf0
7 changed files with 69 additions and 2 deletions

View File

@ -1896,6 +1896,7 @@
three_way_compare, three_way_compare,
thumb2, thumb2,
thumb_mode: "thumb-mode", thumb_mode: "thumb-mode",
time,
tmm_reg, tmm_reg,
to_owned_method, to_owned_method,
to_string, to_string,

View File

@ -446,6 +446,8 @@ trait_selection_type_annotations_needed = {$source_kind ->
} }
.label = type must be known at this point .label = type must be known at this point
trait_selection_type_annotations_needed_error_time = this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update`
trait_selection_types_declared_different = these two types are declared with different lifetimes... 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} trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}

View File

@ -6,7 +6,7 @@
use rustc_errors::{Diag, IntoDiagArg}; use rustc_errors::{Diag, IntoDiagArg};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; 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::intravisit::{self, Visitor};
use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
use rustc_middle::bug; use rustc_middle::bug;
@ -18,7 +18,7 @@
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
}; };
use rustc_span::symbol::{sym, Ident}; 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::error_reporting::TypeErrCtxt;
use crate::errors::{ use crate::errors::{
@ -384,6 +384,7 @@ fn bad_inference_failure_err(
bad_label, bad_label,
was_written: false, was_written: false,
path: Default::default(), path: Default::default(),
time_version: false,
}), }),
TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
span, span,
@ -577,6 +578,10 @@ pub fn emit_inference_failure_err(
} }
} }
} }
let time_version =
self.detect_old_time_crate_version(failure_span, &kind, &mut infer_subdiags);
match error_code { match error_code {
TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired { TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
span, span,
@ -588,6 +593,7 @@ pub fn emit_inference_failure_err(
bad_label: None, bad_label: None,
was_written: path.is_some(), was_written: path.is_some(),
path: path.unwrap_or_default(), path: path.unwrap_or_default(),
time_version,
}), }),
TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
span, span,
@ -613,6 +619,42 @@ pub fn emit_inference_failure_err(
}), }),
} }
} }
/// Detect the inference regression on crate `time` <= 0.3.35 and emit a more targeted error.
/// <https://github.com/rust-lang/rust/issues/127343>
// 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<Span>,
kind: &InferSourceKind<'_>,
// We will clear the non-actionable suggestion from the error to reduce noise.
infer_subdiags: &mut Vec<SourceKindSubdiag<'_>>,
) -> bool {
// FIXME(#129461): We are time-boxing this code in the compiler. It'll start failing
// compilation once we promote 1.89 to beta, which will happen in 9 months from now.
#[cfg(not(version("1.89")))]
const fn version_check() {}
#[cfg(version("1.89"))]
const fn version_check() {
panic!("remove this check as presumably the ecosystem has moved from needing it");
}
const { version_check() };
// Only relevant when building the `time` crate.
if self.infcx.tcx.crate_name(LOCAL_CRATE) == sym::time
&& let Some(span) = span
&& let InferSourceKind::LetBinding { pattern_name, .. } = kind
&& let Some(name) = pattern_name
&& name.as_str() == "items"
&& let FileName::Real(file) = self.infcx.tcx.sess.source_map().span_to_filename(span)
{
let path = file.local_path_if_available().to_string_lossy();
if path.contains("format_description") && path.contains("parse") {
infer_subdiags.clear();
return true;
}
}
false
}
} }
#[derive(Debug)] #[derive(Debug)]

View File

@ -205,6 +205,8 @@ pub struct AnnotationRequired<'a> {
#[note(trait_selection_full_type_written)] #[note(trait_selection_full_type_written)]
pub was_written: bool, pub was_written: bool,
pub path: PathBuf, pub path: PathBuf,
#[note(trait_selection_type_annotations_needed_error_time)]
pub time_version: bool,
} }
// Copy of `AnnotationRequired` for E0283 // Copy of `AnnotationRequired` for E0283

View File

@ -19,6 +19,7 @@
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(associated_type_defaults)] #![feature(associated_type_defaults)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(cfg_version)]
#![feature(control_flow_enum)] #![feature(control_flow_enum)]
#![feature(extract_if)] #![feature(extract_if)]
#![feature(if_let_guard)] #![feature(if_let_guard)]

View File

@ -0,0 +1,8 @@
#![crate_name = "time"]
fn main() {
let items = Box::new(vec![]); //~ ERROR E0282
//~^ NOTE type must be known at this point
//~| NOTE this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35`
items.into();
}

View File

@ -0,0 +1,11 @@
error[E0282]: type annotations needed for `Box<Vec<_>>`
--> $DIR/detect-old-time-version-format_description-parse.rs:4:9
|
LL | let items = Box::new(vec![]);
| ^^^^^ ---------------- type must be known at this point
|
= note: this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0282`.