Auto merge of #128041 - compiler-errors:uplift-errors-into-trait-sel, r=lcnr

Uplift most type-system related error reporting from `rustc_infer` to `rustc_trait_selection`

Completes the major part of #127492. The only cleanup that's needed afterwards is to actually use normalization in favor of the callback where needed, and deleting `can_eq_shallow`.

r? lcnr

Sorry for the large diff! Would prefer if comments can be handled in a follow-up (unless they're absolutely dealbreakers) because it seems bitrotty to let this sit.
This commit is contained in:
bors 2024-07-22 15:06:18 +00:00
commit 20f23abbec
81 changed files with 2601 additions and 2607 deletions

View File

@ -1,6 +1,5 @@
use rustc_errors::Diag;
use rustc_hir::def_id::LocalDefId;
use rustc_infer::error_reporting::infer::nice_region_error::NiceRegionError;
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::region_constraints::Constraint;
use rustc_infer::infer::region_constraints::RegionConstraintData;
@ -14,6 +13,8 @@ use rustc_middle::ty::RegionVid;
use rustc_middle::ty::UniverseIndex;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::infer::nice_region_error::NiceRegionError;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::query::type_op;
use rustc_trait_selection::traits::ObligationCtxt;
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};

View File

@ -35,8 +35,8 @@ use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span, Symbol};
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
use std::iter;

View File

@ -27,7 +27,7 @@ use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Spanned;
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{
type_known_to_meet_bound_modulo_regions, FulfillmentErrorCode,

View File

@ -16,7 +16,7 @@ use rustc_middle::{
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{sym, BytePos, DesugaringKind, Span};
use rustc_target::abi::FieldIdx;
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits;

View File

@ -10,11 +10,6 @@ use rustc_hir::GenericBound::Trait;
use rustc_hir::QPath::Resolved;
use rustc_hir::WherePredicate::BoundPredicate;
use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate};
use rustc_infer::error_reporting::infer::nice_region_error::{
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor,
};
use rustc_infer::error_reporting::infer::region::unexpected_hidden_region_diagnostic;
use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound};
use rustc_middle::bug;
use rustc_middle::hir::place::PlaceBase;
@ -25,6 +20,12 @@ use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_middle::ty::{Region, TyCtxt};
use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::infer::nice_region_error::{
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor,
};
use rustc_trait_selection::error_reporting::infer::region::unexpected_hidden_region_diagnostic;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{Obligation, ObligationCtxt};

View File

@ -14,6 +14,7 @@ use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use crate::{universal_regions::DefiningTy, MirBorrowckCtxt};
@ -457,8 +458,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
) -> RegionNameHighlight {
let mut highlight = RegionHighlightMode::default();
highlight.highlighting_region_vid(self.infcx.tcx, needle_fr, counter);
let type_name =
self.infcx.extract_inference_diagnostics_data(ty.into(), Some(highlight)).name;
let type_name = self
.infcx
.err_ctxt()
.extract_inference_diagnostics_data(ty.into(), Some(highlight))
.name;
debug!(
"highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
@ -872,8 +876,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
let mut highlight = RegionHighlightMode::default();
highlight.highlighting_region_vid(tcx, fr, *self.next_region_name.try_borrow().unwrap());
let type_name =
self.infcx.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight)).name;
let type_name = self
.infcx
.err_ctxt()
.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight))
.name;
let yield_span = match tcx.hir_node(self.mir_hir_id()) {
hir::Node::Expr(hir::Expr {

View File

@ -11,7 +11,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{GenericArgKind, GenericArgs};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::ObligationCtxt;
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;

View File

@ -11,7 +11,7 @@ use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::solve::deeply_normalize;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;

View File

@ -13,7 +13,7 @@ use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
use rustc_middle::ty::{Instance, InstanceKind, TypeVisitableExt};
use rustc_mir_dataflow::Analysis;
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};

View File

@ -26,7 +26,7 @@ use rustc_middle::ty::{
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_target::abi::FieldIdx;
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_type_ir::fold::TypeFoldable;

View File

@ -21,7 +21,7 @@ use rustc_middle::ty::{
use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;

View File

@ -7,7 +7,7 @@ use rustc_session::config::EntryFnType;
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_span::{symbol::sym, Span};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
use std::ops::Not;

View File

@ -82,7 +82,6 @@ use rustc_errors::{pluralize, struct_span_code_err, Diag};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::BitSet;
use rustc_infer::error_reporting::infer::ObligationCauseExt as _;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, TyCtxtInferExt as _};
use rustc_infer::traits::ObligationCause;
@ -96,10 +95,9 @@ use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::traits::suggestions::{
ReturnsVisitor, TypeErrCtxtExt as _,
};
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
use rustc_trait_selection::error_reporting::infer::ObligationCauseExt as _;
use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::ObligationCtxt;
use crate::errors;

View File

@ -29,7 +29,7 @@ use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::misc::{
type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError,

View File

@ -17,7 +17,7 @@ use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::misc::{
type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,

View File

@ -517,9 +517,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UncoveredTyParamCollector<'_, 'tcx> {
if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
return;
}
let Some(origin) = self.infcx.type_var_origin(ty) else {
let ty::Infer(ty::TyVar(vid)) = *ty.kind() else {
return ty.super_visit_with(self);
};
let origin = self.infcx.type_var_origin(vid);
if let Some(def_id) = origin.param_def_id {
self.uncovered_params.insert(def_id);
}
@ -546,9 +547,10 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for TyVarReplacer<'cx, 'tcx> {
if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
return ty;
}
let Some(origin) = self.infcx.type_var_origin(ty) else {
let ty::Infer(ty::TyVar(vid)) = *ty.kind() else {
return ty.super_fold_with(self);
};
let origin = self.infcx.type_var_origin(vid);
if let Some(def_id) = origin.param_def_id {
// The generics of an `impl` don't have a parent, we can index directly.
let index = self.generics.param_def_id_to_index[&def_id];

View File

@ -78,7 +78,7 @@ use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{GenericArg, GenericArgs, GenericArgsRef};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, translate_args_with_cause, wf, ObligationCtxt};

View File

@ -58,8 +58,6 @@ use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{BytePos, DesugaringKind, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtSelectionErrExt as _;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{

View File

@ -53,8 +53,6 @@ use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{self, ObligationCauseCode};
@ -2574,7 +2572,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base: &'tcx hir::Expr<'tcx>,
ty: Ty<'tcx>,
) {
let Some(output_ty) = self.get_impl_future_output_ty(ty) else {
let Some(output_ty) = self.err_ctxt().get_impl_future_output_ty(ty) else {
err.span_label(field_ident.span, "unknown field");
return;
};

View File

@ -175,7 +175,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
};
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
let span = self.infcx.type_var_origin(ty).map(|origin| origin.span).unwrap_or(DUMMY_SP);
let span = ty.ty_vid().map_or(DUMMY_SP, |vid| self.infcx.type_var_origin(vid).span);
self.demand_eqtype(span, ty, fallback);
self.fallback_has_occurred.set(true);
true

View File

@ -19,7 +19,6 @@ use rustc_hir_analysis::hir_ty_lowering::{
GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
};
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::need_type_info::TypeAnnotationNeeded;
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
@ -37,7 +36,7 @@ use rustc_span::hygiene::DesugaringKind;
use rustc_span::symbol::{kw, sym};
use rustc_span::Span;
use rustc_target::abi::FieldIdx;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use rustc_trait_selection::traits::{
self, NormalizeExt, ObligationCauseCode, ObligationCtxt, StructurallyNormalizeExt,
};

View File

@ -338,8 +338,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindAmbiguousParameter<'_, 'tcx> {
type Result = ControlFlow<ty::GenericArg<'tcx>>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if let Some(origin) = self.0.type_var_origin(ty)
&& let Some(def_id) = origin.param_def_id
if let ty::Infer(ty::TyVar(vid)) = *ty.kind()
&& let Some(def_id) = self.0.type_var_origin(vid).param_def_id
&& let generics = self.0.tcx.generics_of(self.1)
&& let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
&& let Some(arg) =

View File

@ -29,7 +29,6 @@ use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
use rustc_hir_analysis::check::potentially_plural_count;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_index::IndexVec;
use rustc_infer::error_reporting::infer::{FailureCode, ObligationCauseExt};
use rustc_infer::infer::TypeTrace;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::ty::adjustment::AllowTwoPhase;
@ -39,6 +38,7 @@ use rustc_middle::{bug, span_bug};
use rustc_session::Session;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{sym, BytePos, Span, DUMMY_SP};
use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};

View File

@ -15,13 +15,13 @@ use hir::def_id::CRATE_DEF_ID;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
use rustc_infer::error_reporting::infer::sub_relations::SubRelations;
use rustc_infer::error_reporting::infer::TypeErrCtxt;
use rustc_infer::infer;
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::Session;
use rustc_span::symbol::Ident;
use rustc_span::{self, sym, Span, DUMMY_SP};
use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations;
use rustc_trait_selection::error_reporting::TypeErrCtxt;
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
use std::cell::{Cell, RefCell};
@ -162,9 +162,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Creates an `TypeErrCtxt` with a reference to the in-progress
/// `TypeckResults` which is used for diagnostics.
/// Use [`InferCtxt::err_ctxt`] to start one without a `TypeckResults`.
/// Use [`InferCtxtErrorExt::err_ctxt`] to start one without a `TypeckResults`.
///
/// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt
/// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt
pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
let mut sub_relations = SubRelations::default();
sub_relations.add_constraints(

View File

@ -32,8 +32,8 @@ use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, Symbol};
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::traits::DefIdOrName;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@ -1107,12 +1107,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.tcx
.instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars));
let ty = match self.tcx.asyncness(fn_id) {
ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!(
fn_decl.output.span(),
"failed to get output type of async function"
)
}),
ty::Asyncness::Yes => {
self.err_ctxt().get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!(
fn_decl.output.span(),
"failed to get output type of async function"
)
})
}
ty::Asyncness::No => ty,
};
let ty = self.normalize(expr.span, ty);

View File

@ -12,7 +12,6 @@ use rustc_hir::HirId;
use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::need_type_info::TypeAnnotationNeeded;
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
use rustc_infer::traits::ObligationCauseCode;
@ -34,6 +33,7 @@ use rustc_span::edit_distance::{
};
use rustc_span::symbol::sym;
use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;

View File

@ -36,7 +36,6 @@ use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{edit_distance, ErrorGuaranteed, ExpnKind, FileName, MacroKind, Span};
use rustc_span::{Symbol, DUMMY_SP};
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedNote;
use rustc_trait_selection::error_reporting::traits::on_unimplemented::TypeErrCtxtExt as _;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{
@ -3276,7 +3275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
return_type: Option<Ty<'tcx>>,
) {
let output_ty = match self.get_impl_future_output_ty(ty) {
let output_ty = match self.err_ctxt().get_impl_future_output_ty(ty) {
Some(output_ty) => self.resolve_vars_if_possible(output_ty),
_ => return,
};

View File

@ -18,7 +18,6 @@ use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{FulfillmentError, ObligationCtxt};
use rustc_type_ir::TyKind::*;

View File

@ -8,7 +8,6 @@ use rustc_errors::{ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirId;
use rustc_infer::infer::need_type_info::TypeAnnotationNeeded;
use rustc_middle::span_bug;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
@ -18,7 +17,7 @@ use rustc_middle::ty::TypeSuperFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use rustc_trait_selection::solve;
use std::mem;

View File

@ -1,397 +1,5 @@
infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
[true] , for some specific lifetime `'{$lifetime}`
*[false] {""}
}
infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
[true] , for some specific lifetime `'{$lifetime}`
*[false] {""}
}
infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime ->
[true] , for some specific lifetime `'{$lifetime}`
*[false] {""}
}
infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$ty_or_sig}` must implement `{$trait_path}`
infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
[true] ...
*[false] {""}
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
[true] ...
*[false] {""}
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
[true] ...
*[false] {""}
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
[true] ...
*[false] {""}
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
infer_ascribe_user_type_prove_predicate = ...so that the where clause holds
infer_await_both_futures = consider `await`ing on both `Future`s
infer_await_future = consider `await`ing on the `Future`
infer_await_note = calling an async function returns a future
infer_but_calling_introduces = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
} has {$lifetime_kind ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement
.label1 = {$has_lifetime ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
}
.label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path ->
[true] `impl` of `{$impl_path}`
*[false] inherent `impl`
}
infer_but_needs_to_satisfy = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
} has {$has_lifetime ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
} but it needs to satisfy a `'static` lifetime requirement
.influencer = this data with {$has_lifetime ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
}...
.require = {$spans_empty ->
*[true] ...is used and required to live as long as `'static` here
[false] ...and is required to live as long as `'static` here
}
.used_here = ...is used here...
.introduced_by_bound = `'static` lifetime requirement introduced by this bound
infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
infer_consider_specifying_length = consider specifying the actual array length
infer_data_flows = ...but data{$label_var1_exists ->
[true] {" "}from `{$label_var1}`
*[false] {""}
} flows{$label_var2_exists ->
[true] {" "}into `{$label_var2}`
*[false] {""}
} here
infer_data_lifetime_flow = ...but data with one lifetime flows into the other here
infer_data_returned = ...but data{$label_var1_exists ->
[true] {" "}from `{$label_var1}`
*[false] {""}
} is returned here
infer_declared_different = this parameter and the return type are declared with different lifetimes...
infer_declared_multiple = this type is declared with multiple lifetimes...
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
.label = lifetime `{$named}` required
infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
.label = lifetime `{$named}` required
infer_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
infer_fn_uniq_types = different fn items have unique types, even if their signatures are the same
infer_fps_cast = consider casting to a fn pointer
infer_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
infer_fps_items_are_distinct = fn items are distinct from fn pointers
infer_fps_remove_ref = consider removing the reference
infer_fps_use_ref = consider using a reference
infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
infer_full_type_written = the full type name has been written to '{$path}'
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
infer_label_bad = {$bad_kind ->
*[other] cannot infer type
[more_info] cannot infer {$prefix_kind ->
*[type] type for {$prefix}
[const_with_param] the value of const parameter
[const] the value of the constant
} `{$name}`{$has_parent ->
[true] {" "}declared on the {$parent_prefix} `{$parent_name}`
*[false] {""}
}
}
infer_lf_bound_not_satisfied = lifetime bound not satisfied
infer_lifetime_mismatch = lifetime mismatch
infer_lifetime_param_suggestion = consider {$is_reuse ->
[true] reusing
*[false] introducing
} a named lifetime parameter{$is_impl ->
[true] {" "}and update trait if needed
*[false] {""}
}
infer_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
infer_meant_str_literal = if you meant to write a string literal, use double quotes
infer_mismatched_static_lifetime = incompatible lifetime on type
infer_more_targeted = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
} has {$has_lifetime ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
} but calling `{$ident}` introduces an implicit `'static` lifetime requirement
infer_msl_introduces_static = introduces a `'static` lifetime requirement
infer_msl_unmet_req = because this has an unmet lifetime requirement
infer_nothing = {""}
infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
infer_oc_closure_selfref = closure/coroutine type that references itself
infer_oc_const_compat = const not compatible with trait
infer_oc_fn_lang_correct_type = {$lang_item_name ->
[panic_impl] `#[panic_handler]`
*[lang_item_name] lang item `{$lang_item_name}`
} function has wrong type
infer_oc_fn_main_correct_type = `main` function has wrong type
infer_oc_fn_start_correct_type = `#[start]` function has wrong type
infer_oc_generic = mismatched types
infer_oc_if_else_different = `if` and `else` have incompatible types
infer_oc_intrinsic_correct_type = intrinsic has wrong type
infer_oc_match_compat = `match` arms have incompatible types
infer_oc_method_compat = method not compatible with trait
infer_oc_method_correct_type = mismatched `self` parameter type
infer_oc_no_diverge = `else` clause of `let...else` does not diverge
infer_oc_no_else = `if` may be missing an `else` clause
infer_oc_try_compat = `?` operator has incompatible types
infer_oc_type_compat = type not compatible with trait
infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
.label = opaque type defined here
infer_opaque_hidden_type =
opaque type's hidden type cannot be another opaque type from the same scope
.label = one of the two opaque types used here has to be outside its defining scope
.opaque_type = opaque type whose hidden type is being assigned
.hidden_type = opaque type being used as hidden type
infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
infer_precise_capturing_existing = add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it
infer_precise_capturing_new = add a `use<...>` bound to explicitly capture `{$new_lifetime}`
infer_precise_capturing_new_but_apit = add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate
infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
infer_prlf_defined_without_sub = the lifetime defined here...
infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
infer_reborrow = ...so that reference does not outlive borrowed content
infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
infer_region_explanation = {$pref_kind ->
*[should_not_happen] [{$pref_kind}]
[ref_valid_for] ...the reference is valid for
[content_valid_for] ...but the borrowed content is only valid for
[type_obj_valid_for] object type is valid for
[source_pointer_valid_for] source pointer is only valid for
[type_satisfy] type must satisfy
[type_outlive] type must outlive
[lf_param_instantiated_with] lifetime parameter instantiated with
[lf_param_must_outlive] but lifetime parameter must outlive
[lf_instantiated_with] lifetime instantiated with
[lf_must_outlive] but lifetime must outlive
[pointer_valid_for] the pointer is valid for
[data_valid_for] but the referenced data is only valid for
[empty] {""}
}{$pref_kind ->
[empty] {""}
*[other] {" "}
}{$desc_kind ->
*[should_not_happen] [{$desc_kind}]
[restatic] the static lifetime
[revar] lifetime {$desc_arg}
[as_defined] the lifetime `{$desc_arg}` as defined here
[as_defined_anon] the anonymous lifetime as defined here
[defined_here] the anonymous lifetime defined here
[defined_here_reg] the lifetime `{$desc_arg}` as defined here
}{$suff_kind ->
*[should_not_happen] [{$suff_kind}]
[empty]{""}
[continues] ...
[req_by_binding] {" "}as required by this binding
}
infer_relate_object_bound = ...so that it can be closed over into an object
infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
[true] ...
*[false] {""}
}
infer_relate_param_bound_2 = ...that is required by this bound
infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
infer_ril_because_of = because of this returned expression
infer_ril_introduced_by = requirement introduced by this return type
infer_ril_introduced_here = `'static` requirement introduced here
infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
infer_source_kind_closure_return =
try giving this closure an explicit return type
# coroutine_kind may need to be translated
infer_source_kind_fully_qualified =
try using a fully qualified path to specify the expected types
infer_source_kind_subdiag_generic_label =
cannot infer {$is_type ->
[true] type
*[false] the value
} of the {$is_type ->
[true] type
*[false] const
} {$parent_exists ->
[true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
*[false] parameter {$param_name}
}
infer_source_kind_subdiag_generic_suggestion =
consider specifying the generic {$arg_count ->
[one] argument
*[other] arguments
}
infer_source_kind_subdiag_let = {$kind ->
[with_pattern] consider giving `{$name}` an explicit type
[closure] consider giving this closure parameter an explicit type
*[other] consider giving this pattern a type
}{$x_kind ->
[has_name] , where the {$prefix_kind ->
*[type] type for {$prefix}
[const_with_param] value of const parameter
[const] value of the constant
} `{$arg_name}` is specified
[underscore] , where the placeholders `_` are specified
*[empty] {""}
}
infer_srs_add = consider returning the local binding `{$ident}`
infer_srs_add_one = consider returning one of these bindings
infer_srs_remove = consider removing this semicolon
infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
infer_stp_wrap_many = try wrapping the pattern in a variant of `{$path}`
infer_stp_wrap_one = try wrapping the pattern in `{$variant}`
infer_subtype = ...so that the {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}
infer_subtype_2 = ...so that {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}
infer_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
infer_suggest_add_let_for_letchains = consider adding `let`
infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
.found = found `{$found}`
.expected = expected `{$expected}`
.expected_found = expected signature `{$expected}`
{" "}found signature `{$found}`
infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
.label_satisfy = doesn't satisfy where-clause
.label_where = due to a where-clause on `{$def_id}`...
.label_dup = implementation of `{$trait_def_id}` is not general enough
infer_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
infer_tuple_trailing_comma = use a trailing comma to create a tuple with one element
infer_type_annotations_needed = {$source_kind ->
[closure] type annotations needed for the closure `{$source_name}`
[normal] type annotations needed for `{$source_name}`
*[other] type annotations needed
}
.label = type must be known at this point
infer_types_declared_different = these two types are declared with different lifetimes...
infer_warn_removing_apit_params = you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable
infer_where_copy_predicates = copy the `where` clause predicates from the trait
infer_where_remove = remove the `where` clause

View File

@ -1 +0,0 @@
pub mod infer;

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,6 @@ pub use BoundRegionConversionTime::*;
pub use RegionVariableOrigin::*;
pub use SubregionOrigin::*;
use crate::error_reporting::infer::TypeErrCtxt;
use crate::infer::relate::RelateResult;
use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
use free_regions::RegionRelations;
@ -24,7 +23,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::undo_log::Rollback;
use rustc_data_structures::unify as ut;
use rustc_errors::{Diag, ErrorGuaranteed};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::extension;
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
@ -65,8 +65,6 @@ pub mod relate;
pub mod resolve;
pub(crate) mod snapshot;
pub mod type_variable;
// FIXME(error_reporting): Where should we put this?
pub mod need_type_info;
#[must_use]
#[derive(Debug)]
@ -698,36 +696,24 @@ impl<'tcx> InferCtxt<'tcx> {
self.next_trait_solver
}
/// Creates a `TypeErrCtxt` for emitting various inference errors.
/// During typeck, use `FnCtxt::err_ctxt` instead.
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
TypeErrCtxt {
infcx: self,
sub_relations: Default::default(),
typeck_results: None,
fallback_has_occurred: false,
normalize_fn_sig: Box::new(|fn_sig| fn_sig),
autoderef_steps: Box::new(|ty| {
debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
vec![(ty, vec![])]
}),
}
}
pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
t.fold_with(&mut self.freshener())
}
/// Returns the origin of the type variable identified by `vid`, or `None`
/// if this is not a type variable.
/// Returns the origin of the type variable identified by `vid`.
///
/// No attempt is made to resolve `ty`.
pub fn type_var_origin(&self, ty: Ty<'tcx>) -> Option<TypeVariableOrigin> {
match *ty.kind() {
ty::Infer(ty::TyVar(vid)) => {
Some(self.inner.borrow_mut().type_variables().var_origin(vid))
}
_ => None,
/// No attempt is made to resolve `vid` to its root variable.
pub fn type_var_origin(&self, vid: TyVid) -> TypeVariableOrigin {
self.inner.borrow_mut().type_variables().var_origin(vid)
}
/// Returns the origin of the const variable identified by `vid`
// FIXME: We should store origins separately from the unification table
// so this doesn't need to be optional.
pub fn const_var_origin(&self, vid: ConstVid) -> Option<ConstVariableOrigin> {
match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
ConstVariableValue::Known { .. } => None,
ConstVariableValue::Unknown { origin, .. } => Some(origin),
}
}
@ -1589,60 +1575,6 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// [Note-Type-error-reporting]
// An invariant is that anytime the expected or actual type is Error (the special
// error type, meaning that an error occurred when typechecking this expression),
// this is a derived error. The error cascaded from another error (that was already
// reported), so it's not useful to display it to the user.
// The following methods implement this logic.
// They check if either the actual or expected type is Error, and don't print the error
// in this case. The typechecker should only ever report type errors involving mismatched
// types using one of these methods, and should not call span_err directly for such
// errors.
pub fn type_error_struct_with_diag<M>(
&self,
sp: Span,
mk_diag: M,
actual_ty: Ty<'tcx>,
) -> Diag<'a>
where
M: FnOnce(String) -> Diag<'a>,
{
let actual_ty = self.resolve_vars_if_possible(actual_ty);
debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
let mut err = mk_diag(self.ty_to_string(actual_ty));
// Don't report an error if actual type is `Error`.
if actual_ty.references_error() {
err.downgrade_to_delayed_bug();
}
err
}
pub fn report_mismatched_types(
&self,
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
err: TypeError<'tcx>,
) -> Diag<'a> {
self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err)
}
pub fn report_mismatched_consts(
&self,
cause: &ObligationCause<'tcx>,
expected: ty::Const<'tcx>,
actual: ty::Const<'tcx>,
err: TypeError<'tcx>,
) -> Diag<'a> {
self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err)
}
}
/// 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)]
@ -1888,3 +1820,32 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
}
impl<'tcx> InferCtxt<'tcx> {
/// Given a [`hir::Block`], get the span of its last expression or
/// statement, peeling off any inner blocks.
pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
let block = block.innermost_block();
if let Some(expr) = &block.expr {
expr.span
} else if let Some(stmt) = block.stmts.last() {
// possibly incorrect trailing `;` in the else arm
stmt.span
} else {
// empty block; point at its entirety
block.span
}
}
/// Given a [`hir::HirId`] for a block, get the span of its last expression
/// or statement, peeling off any inner blocks.
pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
match self.tcx.hir_node(hir_id) {
hir::Node::Block(blk) => self.find_block_span(blk),
// The parser was in a weird state if either of these happen, but
// it's better not to panic.
hir::Node::Expr(e) => e.span,
_ => rustc_span::DUMMY_SP,
}
}
}

View File

@ -34,7 +34,6 @@
#[macro_use]
extern crate tracing;
pub mod error_reporting;
mod errors;
pub mod infer;
pub mod traits;

View File

@ -1,203 +0,0 @@
use super::ObjectSafetyViolation;
use crate::infer::InferCtxt;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Span;
use std::fmt;
use std::iter;
impl<'tcx> InferCtxt<'tcx> {
pub fn report_extra_impl_obligation<'a>(
&'a self,
error_span: Span,
impl_item_def_id: LocalDefId,
trait_item_def_id: DefId,
requirement: &dyn fmt::Display,
) -> Diag<'a> {
let mut err = struct_span_code_err!(
self.dcx(),
error_span,
E0276,
"impl has stricter requirements than trait"
);
if !self.tcx.is_impl_trait_in_trait(trait_item_def_id) {
if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) {
let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
err.span_label(span, format!("definition of `{item_name}` from trait"));
}
}
err.span_label(error_span, format!("impl has extra requirement {requirement}"));
err
}
}
pub fn report_object_safety_error<'tcx>(
tcx: TyCtxt<'tcx>,
span: Span,
hir_id: Option<hir::HirId>,
trait_def_id: DefId,
violations: &[ObjectSafetyViolation],
) -> Diag<'tcx> {
let trait_str = tcx.def_path_str(trait_def_id);
let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node {
hir::Node::Item(item) => Some(item.ident.span),
_ => None,
});
let mut err = struct_span_code_err!(
tcx.dcx(),
span,
E0038,
"the trait `{}` cannot be made into an object",
trait_str
);
err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
if let Some(hir_id) = hir_id
&& let hir::Node::Ty(ty) = tcx.hir_node(hir_id)
&& let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
{
let mut hir_id = hir_id;
while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) {
hir_id = ty.hir_id;
}
if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
// Do not suggest `impl Trait` when dealing with things like super-traits.
err.span_suggestion_verbose(
ty.span.until(trait_ref.span),
"consider using an opaque type instead",
"impl ",
Applicability::MaybeIncorrect,
);
}
}
let mut reported_violations = FxIndexSet::default();
let mut multi_span = vec![];
let mut messages = vec![];
for violation in violations {
if let ObjectSafetyViolation::SizedSelf(sp) = &violation
&& !sp.is_empty()
{
// Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
// with a `Span`.
reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
}
if reported_violations.insert(violation.clone()) {
let spans = violation.spans();
let msg = if trait_span.is_none() || spans.is_empty() {
format!("the trait cannot be made into an object because {}", violation.error_msg())
} else {
format!("...because {}", violation.error_msg())
};
if spans.is_empty() {
err.note(msg);
} else {
for span in spans {
multi_span.push(span);
messages.push(msg.clone());
}
}
}
}
let has_multi_span = !multi_span.is_empty();
let mut note_span = MultiSpan::from_spans(multi_span.clone());
if let (Some(trait_span), true) = (trait_span, has_multi_span) {
note_span.push_span_label(trait_span, "this trait cannot be made into an object...");
}
for (span, msg) in iter::zip(multi_span, messages) {
note_span.push_span_label(span, msg);
}
err.span_note(
note_span,
"for a trait to be \"object safe\" it needs to allow building a vtable to allow the call \
to be resolvable dynamically; for more information visit \
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
);
// Only provide the help if its a local trait, otherwise it's not actionable.
if trait_span.is_some() {
let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
reported_violations.sort();
let mut potential_solutions: Vec<_> =
reported_violations.into_iter().map(|violation| violation.solution()).collect();
potential_solutions.sort();
// Allows us to skip suggesting that the same item should be moved to another trait multiple times.
potential_solutions.dedup();
for solution in potential_solutions {
solution.add_to(&mut err);
}
}
let impls_of = tcx.trait_impls_of(trait_def_id);
let impls = if impls_of.blanket_impls().is_empty() {
impls_of
.non_blanket_impls()
.values()
.flatten()
.filter(|def_id| {
!matches!(tcx.type_of(*def_id).instantiate_identity().kind(), ty::Dynamic(..))
})
.collect::<Vec<_>>()
} else {
vec![]
};
let externally_visible = if !impls.is_empty()
&& let Some(def_id) = trait_def_id.as_local()
// We may be executing this during typeck, which would result in cycle
// if we used effective_visibilities query, which looks into opaque types
// (and therefore calls typeck).
&& tcx.resolutions(()).effective_visibilities.is_exported(def_id)
{
true
} else {
false
};
match &impls[..] {
[] => {}
_ if impls.len() > 9 => {}
[only] if externally_visible => {
err.help(with_no_trimmed_paths!(format!(
"only type `{}` is seen to implement the trait in this crate, consider using it \
directly instead",
tcx.type_of(*only).instantiate_identity(),
)));
}
[only] => {
err.help(with_no_trimmed_paths!(format!(
"only type `{}` implements the trait, consider using it directly instead",
tcx.type_of(*only).instantiate_identity(),
)));
}
impls => {
let types = impls
.iter()
.map(|t| {
with_no_trimmed_paths!(format!(" {}", tcx.type_of(*t).instantiate_identity(),))
})
.collect::<Vec<_>>();
err.help(format!(
"the following types implement the trait, consider defining an enum where each \
variant holds one of these types, implementing `{}` for this new enum and using \
it instead:\n{}",
trait_str,
types.join("\n"),
));
}
}
if externally_visible {
err.note(format!(
"`{trait_str}` can be implemented in other crates; if you want to support your users \
passing their own types here, you can't refer to a specific type",
));
}
err
}

View File

@ -3,7 +3,6 @@
//! [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
mod engine;
pub mod error_reporting;
mod project;
mod structural_impls;
pub mod util;

View File

@ -81,7 +81,7 @@ use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_target::spec::PanicStrategy;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::TyCtxtInferExt as _;
use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};

View File

@ -34,7 +34,7 @@ use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{BytePos, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
use rustc_trait_selection::traits::ObligationCtxt;
use std::cell::Cell;

View File

@ -8,7 +8,7 @@ use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::{infer::TyCtxtInferExt, traits};
use crate::errors::{

View File

@ -1,3 +1,65 @@
trait_selection_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
[true] , for some specific lifetime `'{$lifetime}`
*[false] {""}
}
trait_selection_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
[true] , for some specific lifetime `'{$lifetime}`
*[false] {""}
}
trait_selection_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime ->
[true] , for some specific lifetime `'{$lifetime}`
*[false] {""}
}
trait_selection_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
trait_selection_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$ty_or_sig}` must implement `{$trait_path}`
trait_selection_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
trait_selection_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
trait_selection_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
trait_selection_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
trait_selection_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
trait_selection_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
[true] ...
*[false] {""}
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
trait_selection_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
[true] ...
*[false] {""}
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
trait_selection_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
[true] ...
*[false] {""}
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
trait_selection_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
[true] ...
*[false] {""}
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
trait_selection_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
[true] ...
*[false] {""}
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
trait_selection_adjust_signature_borrow = consider adjusting the signature so it borrows its {$len ->
[one] argument
*[other] arguments
@ -8,8 +70,48 @@ trait_selection_adjust_signature_remove_borrow = consider adjusting the signatur
*[other] arguments
}
trait_selection_ascribe_user_type_prove_predicate = ...so that the where clause holds
trait_selection_async_closure_not_fn = async closure does not implement `{$kind}` because it captures state from its environment
trait_selection_await_both_futures = consider `await`ing on both `Future`s
trait_selection_await_future = consider `await`ing on the `Future`
trait_selection_await_note = calling an async function returns a future
trait_selection_but_calling_introduces = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
} has {$lifetime_kind ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement
.label1 = {$has_lifetime ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
}
.label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path ->
[true] `impl` of `{$impl_path}`
*[false] inherent `impl`
}
trait_selection_but_needs_to_satisfy = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
} has {$has_lifetime ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
} but it needs to satisfy a `'static` lifetime requirement
.influencer = this data with {$has_lifetime ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
}...
.require = {$spans_empty ->
*[true] ...is used and required to live as long as `'static` here
[false] ...and is required to live as long as `'static` here
}
.used_here = ...is used here...
.introduced_by_bound = `'static` lifetime requirement introduced by this bound
trait_selection_closure_fn_mut_label = closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here
trait_selection_closure_fn_once_label = closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment
@ -19,18 +121,67 @@ trait_selection_closure_kind_mismatch = expected a closure that implements the `
trait_selection_closure_kind_requirement = the requirement to implement `{$trait_prefix}{$expected}` derives from here
trait_selection_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
trait_selection_consider_specifying_length = consider specifying the actual array length
trait_selection_data_flows = ...but data{$label_var1_exists ->
[true] {" "}from `{$label_var1}`
*[false] {""}
} flows{$label_var2_exists ->
[true] {" "}into `{$label_var2}`
*[false] {""}
} here
trait_selection_data_lifetime_flow = ...but data with one lifetime flows into the other here
trait_selection_data_returned = ...but data{$label_var1_exists ->
[true] {" "}from `{$label_var1}`
*[false] {""}
} is returned here
trait_selection_declared_different = this parameter and the return type are declared with different lifetimes...
trait_selection_declared_multiple = this type is declared with multiple lifetimes...
trait_selection_disallowed_positional_argument = positional format arguments are not allowed here
.help = only named format arguments with the name of one of the generic types are allowed in this context
trait_selection_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
trait_selection_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement
trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement
trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
.label = empty on-clause here
trait_selection_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
trait_selection_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
trait_selection_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
.label = lifetime `{$named}` required
trait_selection_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
.label = lifetime `{$named}` required
trait_selection_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
trait_selection_fn_uniq_types = different fn items have unique types, even if their signatures are the same
trait_selection_fps_cast = consider casting to a fn pointer
trait_selection_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
trait_selection_fps_items_are_distinct = fn items are distinct from fn pointers
trait_selection_fps_remove_ref = consider removing the reference
trait_selection_fps_use_ref = consider using a reference
trait_selection_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
trait_selection_full_type_written = the full type name has been written to '{$path}'
trait_selection_ignored_diagnostic_option = `{$option_name}` is ignored due to previous definition of `{$option_name}`
.other_label = `{$option_name}` is first declared here
.label = `{$option_name}` is already declared here
trait_selection_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
trait_selection_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}`
trait_selection_invalid_format_specifier = invalid format specifier
@ -39,13 +190,52 @@ trait_selection_invalid_format_specifier = invalid format specifier
trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
.label = invalid on-clause here
trait_selection_label_bad = {$bad_kind ->
*[other] cannot infer type
[more_info] cannot infer {$prefix_kind ->
*[type] type for {$prefix}
[const_with_param] the value of const parameter
[const] the value of the constant
} `{$name}`{$has_parent ->
[true] {" "}declared on the {$parent_prefix} `{$parent_name}`
*[false] {""}
}
}
trait_selection_lf_bound_not_satisfied = lifetime bound not satisfied
trait_selection_lifetime_mismatch = lifetime mismatch
trait_selection_lifetime_param_suggestion = consider {$is_reuse ->
[true] reusing
*[false] introducing
} a named lifetime parameter{$is_impl ->
[true] {" "}and update trait if needed
*[false] {""}
}
trait_selection_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
trait_selection_malformed_on_unimplemented_attr = malformed `on_unimplemented` attribute
.help = only `message`, `note` and `label` are allowed as options
.label = invalid option found here
trait_selection_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
trait_selection_meant_char_literal = if you meant to write a `char` literal, use single quotes
trait_selection_meant_str_literal = if you meant to write a string literal, use double quotes
trait_selection_mismatched_static_lifetime = incompatible lifetime on type
trait_selection_missing_options_for_on_unimplemented_attr = missing options for `on_unimplemented` attribute
.help = at least one of the `message`, `note` and `label` options are expected
trait_selection_more_targeted = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
} has {$has_lifetime ->
[true] lifetime `{$lifetime}`
*[false] an anonymous lifetime `'_`
} but calling `{$ident}` introduces an implicit `'static` lifetime requirement
trait_selection_msl_introduces_static = introduces a `'static` lifetime requirement
trait_selection_msl_unmet_req = because this has an unmet lifetime requirement
trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
[none] {""}
*[default] {" "}for type `{$self_desc}`
@ -59,13 +249,214 @@ trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a
.label = expected value here
.note = eg `#[rustc_on_unimplemented(message="foo")]`
trait_selection_nothing = {""}
trait_selection_oc_cant_coerce = cannot coerce intrinsics to function pointers
trait_selection_oc_closure_selfref = closure/coroutine type that references itself
trait_selection_oc_const_compat = const not compatible with trait
trait_selection_oc_fn_lang_correct_type = {$lang_item_name ->
[panic_impl] `#[panic_handler]`
*[lang_item_name] lang item `{$lang_item_name}`
} function has wrong type
trait_selection_oc_fn_main_correct_type = `main` function has wrong type
trait_selection_oc_fn_start_correct_type = `#[start]` function has wrong type
trait_selection_oc_generic = mismatched types
trait_selection_oc_if_else_different = `if` and `else` have incompatible types
trait_selection_oc_intrinsic_correct_type = intrinsic has wrong type
trait_selection_oc_match_compat = `match` arms have incompatible types
trait_selection_oc_method_compat = method not compatible with trait
trait_selection_oc_method_correct_type = mismatched `self` parameter type
trait_selection_oc_no_diverge = `else` clause of `let...else` does not diverge
trait_selection_oc_no_else = `if` may be missing an `else` clause
trait_selection_oc_try_compat = `?` operator has incompatible types
trait_selection_oc_type_compat = type not compatible with trait
trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
.label = opaque type defined here
trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content...
trait_selection_precise_capturing_existing = add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it
trait_selection_precise_capturing_new = add a `use<...>` bound to explicitly capture `{$new_lifetime}`
trait_selection_precise_capturing_new_but_apit = add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate
trait_selection_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
trait_selection_prlf_defined_without_sub = the lifetime defined here...
trait_selection_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
trait_selection_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
trait_selection_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
trait_selection_reborrow = ...so that reference does not outlive borrowed content
trait_selection_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
trait_selection_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
trait_selection_region_explanation = {$pref_kind ->
*[should_not_happen] [{$pref_kind}]
[ref_valid_for] ...the reference is valid for
[content_valid_for] ...but the borrowed content is only valid for
[type_obj_valid_for] object type is valid for
[source_pointer_valid_for] source pointer is only valid for
[type_satisfy] type must satisfy
[type_outlive] type must outlive
[lf_param_instantiated_with] lifetime parameter instantiated with
[lf_param_must_outlive] but lifetime parameter must outlive
[lf_instantiated_with] lifetime instantiated with
[lf_must_outlive] but lifetime must outlive
[pointer_valid_for] the pointer is valid for
[data_valid_for] but the referenced data is only valid for
[empty] {""}
}{$pref_kind ->
[empty] {""}
*[other] {" "}
}{$desc_kind ->
*[should_not_happen] [{$desc_kind}]
[restatic] the static lifetime
[revar] lifetime {$desc_arg}
[as_defined] the lifetime `{$desc_arg}` as defined here
[as_defined_anon] the anonymous lifetime as defined here
[defined_here] the anonymous lifetime defined here
[defined_here_reg] the lifetime `{$desc_arg}` as defined here
}{$suff_kind ->
*[should_not_happen] [{$suff_kind}]
[empty]{""}
[continues] ...
[req_by_binding] {" "}as required by this binding
}
trait_selection_relate_object_bound = ...so that it can be closed over into an object
trait_selection_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
[true] ...
*[false] {""}
}
trait_selection_relate_param_bound_2 = ...that is required by this bound
trait_selection_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
trait_selection_ril_because_of = because of this returned expression
trait_selection_ril_introduced_by = requirement introduced by this return type
trait_selection_ril_introduced_here = `'static` requirement introduced here
trait_selection_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
trait_selection_source_kind_closure_return =
try giving this closure an explicit return type
# coroutine_kind may need to be translated
trait_selection_source_kind_fully_qualified =
try using a fully qualified path to specify the expected types
trait_selection_source_kind_subdiag_generic_label =
cannot infer {$is_type ->
[true] type
*[false] the value
} of the {$is_type ->
[true] type
*[false] const
} {$parent_exists ->
[true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
*[false] parameter {$param_name}
}
trait_selection_source_kind_subdiag_generic_suggestion =
consider specifying the generic {$arg_count ->
[one] argument
*[other] arguments
}
trait_selection_source_kind_subdiag_let = {$kind ->
[with_pattern] consider giving `{$name}` an explicit type
[closure] consider giving this closure parameter an explicit type
*[other] consider giving this pattern a type
}{$x_kind ->
[has_name] , where the {$prefix_kind ->
*[type] type for {$prefix}
[const_with_param] value of const parameter
[const] value of the constant
} `{$arg_name}` is specified
[underscore] , where the placeholders `_` are specified
*[empty] {""}
}
trait_selection_srs_add = consider returning the local binding `{$ident}`
trait_selection_srs_add_one = consider returning one of these bindings
trait_selection_srs_remove = consider removing this semicolon
trait_selection_srs_remove_and_box = consider removing this semicolon and boxing the expressions
trait_selection_stp_wrap_many = try wrapping the pattern in a variant of `{$path}`
trait_selection_stp_wrap_one = try wrapping the pattern in `{$variant}`
trait_selection_subtype = ...so that the {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}
trait_selection_subtype_2 = ...so that {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
[expr_assignable] expression is assignable
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
[fn_lang_correct_type] lang item function has the correct type
[intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}
trait_selection_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
trait_selection_suggest_add_let_for_letchains = consider adding `let`
trait_selection_tid_consider_borrowing = consider borrowing this type parameter in the trait
trait_selection_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
trait_selection_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
trait_selection_trait_has_no_impls = this trait has no implementations, consider adding one
trait_selection_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
.found = found `{$found}`
.expected = expected `{$expected}`
.expected_found = expected signature `{$expected}`
{" "}found signature `{$found}`
trait_selection_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
.label_satisfy = doesn't satisfy where-clause
.label_where = due to a where-clause on `{$def_id}`...
.label_dup = implementation of `{$trait_def_id}` is not general enough
trait_selection_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
trait_selection_tuple_trailing_comma = use a trailing comma to create a tuple with one element
trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead
trait_selection_type_annotations_needed = {$source_kind ->
[closure] type annotations needed for the closure `{$source_name}`
[normal] type annotations needed for `{$source_name}`
*[other] type annotations needed
}
.label = type must be known at this point
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_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}`
.help = expect either a generic argument name or {"`{Self}`"} as format argument
trait_selection_warn_removing_apit_params = you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable
trait_selection_where_copy_predicates = copy the `where` clause predicates from the trait
trait_selection_where_remove = remove the `where` clause
trait_selection_wrapped_parser_error = {$description}
.label = {$label}

View File

@ -46,14 +46,12 @@
//! time of error detection.
use std::borrow::Cow;
use std::ops::{ControlFlow, Deref};
use std::ops::ControlFlow;
use std::path::PathBuf;
use std::{cmp, fmt, iter};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::{
pluralize, Applicability, Diag, DiagCtxtHandle, DiagStyledString, IntoDiagArg, StringPart,
};
use rustc_errors::{pluralize, Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
@ -72,23 +70,23 @@ use rustc_middle::ty::{
use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
use crate::error_reporting::TypeErrCtxt;
use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags};
use crate::infer;
use crate::infer::relate::{self, RelateResult, TypeRelation};
use crate::infer::{InferCtxt, TypeTrace, ValuePairs};
use crate::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
PredicateObligation,
};
mod note_and_explain;
mod suggest;
pub mod need_type_info;
pub mod nice_region_error;
pub mod region;
pub mod sub_relations;
pub mod nice_region_error;
/// Makes a valid string literal from a string by escaping special characters (" and \),
/// unless they are already escaped.
fn escape_literal(s: &str) -> String {
@ -111,48 +109,59 @@ fn escape_literal(s: &str) -> String {
escaped
}
/// A helper for building type related errors. The `typeck_results`
/// field is only populated during an in-progress typeck.
/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
///
/// You must only create this if you intend to actually emit an error (or
/// perhaps a warning, though preferably not.) It provides a lot of utility
/// methods which should not be used during the happy path.
pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'tcx>,
pub sub_relations: std::cell::RefCell<sub_relations::SubRelations>,
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
pub fallback_has_occurred: bool,
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
pub autoderef_steps:
Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
}
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pub fn dcx(&self) -> DiagCtxtHandle<'a> {
self.infcx.dcx()
// [Note-Type-error-reporting]
// An invariant is that anytime the expected or actual type is Error (the special
// error type, meaning that an error occurred when typechecking this expression),
// this is a derived error. The error cascaded from another error (that was already
// reported), so it's not useful to display it to the user.
// The following methods implement this logic.
// They check if either the actual or expected type is Error, and don't print the error
// in this case. The typechecker should only ever report type errors involving mismatched
// types using one of these methods, and should not call span_err directly for such
// errors.
pub fn type_error_struct_with_diag<M>(
&self,
sp: Span,
mk_diag: M,
actual_ty: Ty<'tcx>,
) -> Diag<'a>
where
M: FnOnce(String) -> Diag<'a>,
{
let actual_ty = self.resolve_vars_if_possible(actual_ty);
debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
let mut err = mk_diag(self.ty_to_string(actual_ty));
// Don't report an error if actual type is `Error`.
if actual_ty.references_error() {
err.downgrade_to_delayed_bug();
}
err
}
/// This is just to avoid a potential footgun of accidentally
/// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
#[deprecated(note = "you already have a `TypeErrCtxt`")]
#[allow(unused)]
pub fn err_ctxt(&self) -> ! {
bug!("called `err_ctxt` on `TypeErrCtxt`. Try removing the call");
pub fn report_mismatched_types(
&self,
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
err: TypeError<'tcx>,
) -> Diag<'a> {
self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err)
}
}
impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> {
type Target = InferCtxt<'tcx>;
fn deref(&self) -> &InferCtxt<'tcx> {
self.infcx
pub fn report_mismatched_consts(
&self,
cause: &ObligationCause<'tcx>,
expected: ty::Const<'tcx>,
actual: ty::Const<'tcx>,
err: TypeError<'tcx>,
) -> Diag<'a> {
self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err)
}
}
impl<'tcx> InferCtxt<'tcx> {
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
let (def_id, args) = match *ty.kind() {
ty::Alias(_, ty::AliasTy { def_id, args, .. })
@ -189,9 +198,7 @@ impl<'tcx> InferCtxt<'tcx> {
.flatten()
})
}
}
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// Adds a note if the types come from similarly named crates
fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) {
use hir::def_id::CrateNum;
@ -2190,32 +2197,3 @@ impl TyCategory {
}
}
}
impl<'tcx> InferCtxt<'tcx> {
/// Given a [`hir::Block`], get the span of its last expression or
/// statement, peeling off any inner blocks.
pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
let block = block.innermost_block();
if let Some(expr) = &block.expr {
expr.span
} else if let Some(stmt) = block.stmts.last() {
// possibly incorrect trailing `;` in the else arm
stmt.span
} else {
// empty block; point at its entirety
block.span
}
}
/// Given a [`hir::HirId`] for a block, get the span of its last expression
/// or statement, peeling off any inner blocks.
pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
match self.tcx.hir_node(hir_id) {
hir::Node::Block(blk) => self.find_block_span(blk),
// The parser was in a weird state if either of these happen, but
// it's better not to panic.
hir::Node::Expr(e) => e.span,
_ => rustc_span::DUMMY_SP,
}
}
}

View File

@ -1,4 +1,4 @@
use crate::error_reporting::infer::TypeErrCtxt;
use crate::error_reporting::TypeErrCtxt;
use crate::errors::{
AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError,
SourceKindMultiSuggestion, SourceKindSubdiag,
@ -13,7 +13,6 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::infer::unify_key::ConstVariableValue;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
use rustc_middle::ty::{
@ -183,9 +182,7 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
warn!("resolved ty var in error message");
}
let mut infcx_inner = infcx.inner.borrow_mut();
let ty_vars = infcx_inner.type_variables();
let var_origin = ty_vars.var_origin(ty_vid);
let var_origin = infcx.type_var_origin(ty_vid);
if let Some(def_id) = var_origin.param_def_id
// The `Self` param of a trait has the def-id of the trait,
// since it's a synthetic parameter.
@ -206,24 +203,8 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
}
};
printer.ty_infer_name_resolver = Some(Box::new(ty_getter));
let const_getter = move |ct_vid| match infcx
.inner
.borrow_mut()
.const_unification_table()
.probe_value(ct_vid)
{
ConstVariableValue::Known { value: _ } => {
warn!("resolved const var in error message");
None
}
ConstVariableValue::Unknown { origin, universe: _ } => {
if let Some(def_id) = origin.param_def_id {
Some(infcx.tcx.item_name(def_id))
} else {
None
}
}
};
let const_getter =
move |ct_vid| Some(infcx.tcx.item_name(infcx.const_var_origin(ct_vid)?.param_def_id?));
printer.const_infer_name_resolver = Some(Box::new(const_getter));
printer
}
@ -289,7 +270,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
format!("fn({args}){ret}")
}
impl<'tcx> InferCtxt<'tcx> {
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// Extracts data used by diagnostic for either types or constants
/// which were stuck during inference.
pub fn extract_inference_diagnostics_data(
@ -300,9 +281,7 @@ impl<'tcx> InferCtxt<'tcx> {
match arg.unpack() {
GenericArgKind::Type(ty) => {
if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
let mut inner = self.inner.borrow_mut();
let ty_vars = &inner.type_variables();
let var_origin = ty_vars.var_origin(ty_vid);
let var_origin = self.infcx.type_var_origin(ty_vid);
if let Some(def_id) = var_origin.param_def_id
// The `Self` param of a trait has the def-id of the trait,
// since it's a synthetic parameter.
@ -332,13 +311,7 @@ impl<'tcx> InferCtxt<'tcx> {
}
GenericArgKind::Const(ct) => {
if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
let origin =
match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
ConstVariableValue::Known { value } => {
bug!("resolved infer var: {vid:?} {value}")
}
ConstVariableValue::Unknown { origin, universe: _ } => origin,
};
let origin = self.const_var_origin(vid).expect("expected unresolved const var");
if let Some(def_id) = origin.param_def_id {
return InferenceDiagnosticsData {
name: self.tcx.item_name(def_id).to_string(),
@ -391,7 +364,7 @@ impl<'tcx> InferCtxt<'tcx> {
span: Span,
arg_data: InferenceDiagnosticsData,
error_code: TypeAnnotationNeeded,
) -> Diag<'_> {
) -> Diag<'a> {
let source_kind = "other";
let source_name = "";
let failure_span = None;
@ -434,9 +407,7 @@ impl<'tcx> InferCtxt<'tcx> {
}),
}
}
}
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
#[instrument(level = "debug", skip(self, error_code))]
pub fn emit_inference_failure_err(
&self,
@ -453,7 +424,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// If we don't have any typeck results we're outside
// of a body, so we won't be able to get better info
// here.
return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code);
return self.bad_inference_failure_err(failure_span, arg_data, error_code);
};
let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg);
@ -465,7 +436,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
let Some(InferSource { span, kind }) = local_visitor.infer_source else {
return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code);
return self.bad_inference_failure_err(failure_span, arg_data, error_code);
};
let (source_kind, name, path) = kind.ty_localized_msg(self);
@ -887,7 +858,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
use ty::InferConst::*;
match (inner_ct.kind(), target_ct.kind()) {
(ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => {
self.tecx.inner.borrow_mut().const_unification_table().unioned(a_vid, b_vid)
self.tecx.root_const_var(a_vid) == self.tecx.root_const_var(b_vid)
}
_ => false,
}

View File

@ -1,4 +1,4 @@
use crate::error_reporting::infer::TypeErrCtxt;
use crate::error_reporting::TypeErrCtxt;
use crate::infer::RegionResolutionError;
use crate::infer::RegionResolutionError::*;
use rustc_errors::{Diag, ErrorGuaranteed};

View File

@ -1,4 +1,3 @@
use super::TypeErrCtxt;
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
use rustc_errors::{pluralize, Diag, MultiSpan};
use rustc_hir as hir;
@ -12,6 +11,8 @@ use rustc_middle::{
};
use rustc_span::{def_id::DefId, sym, BytePos, Span, Symbol};
use crate::error_reporting::TypeErrCtxt;
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pub fn note_and_explain_type_err(
&self,

View File

@ -18,7 +18,8 @@ use rustc_type_ir::Upcast as _;
use super::nice_region_error::find_anon_type;
use super::{nice_region_error, ObligationCauseAsDiagArg};
use crate::error_reporting::infer::{ObligationCauseExt as _, TypeErrCtxt};
use crate::error_reporting::infer::ObligationCauseExt as _;
use crate::error_reporting::TypeErrCtxt;
use crate::errors::{
self, note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound,
OutlivesContent, RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
@ -224,16 +225,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
.add_to_diag(err),
infer::Reborrow(span) => {
RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diag(err)
RegionOriginNote::Plain { span, msg: fluent::trait_selection_reborrow }
.add_to_diag(err)
}
infer::RelateObjectBound(span) => {
RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_object_bound }
.add_to_diag(err);
}
infer::ReferenceOutlivesReferent(ty, span) => {
RegionOriginNote::WithName {
span,
msg: fluent::infer_reference_outlives_referent,
msg: fluent::trait_selection_reference_outlives_referent,
name: &self.ty_to_string(ty),
continues: false,
}
@ -242,23 +244,32 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
infer::RelateParamBound(span, ty, opt_span) => {
RegionOriginNote::WithName {
span,
msg: fluent::infer_relate_param_bound,
msg: fluent::trait_selection_relate_param_bound,
name: &self.ty_to_string(ty),
continues: opt_span.is_some(),
}
.add_to_diag(err);
if let Some(span) = opt_span {
RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
.add_to_diag(err);
RegionOriginNote::Plain {
span,
msg: fluent::trait_selection_relate_param_bound_2,
}
.add_to_diag(err);
}
}
infer::RelateRegionParamBound(span) => {
RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
.add_to_diag(err);
RegionOriginNote::Plain {
span,
msg: fluent::trait_selection_relate_region_param_bound,
}
.add_to_diag(err);
}
infer::CompareImplItemObligation { span, .. } => {
RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
.add_to_diag(err);
RegionOriginNote::Plain {
span,
msg: fluent::trait_selection_compare_impl_item_obligation,
}
.add_to_diag(err);
}
infer::CheckAssociatedTypeBounds { ref parent, .. } => {
self.note_region_origin(err, parent);
@ -266,7 +277,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
infer::AscribeUserTypeProvePredicate(span) => {
RegionOriginNote::Plain {
span,
msg: fluent::infer_ascribe_user_type_prove_predicate,
msg: fluent::trait_selection_ascribe_user_type_prove_predicate,
}
.add_to_diag(err);
}
@ -445,7 +456,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
})
}
infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
let mut err = self.infcx.report_extra_impl_obligation(
let mut err = self.report_extra_impl_obligation(
span,
impl_item_def_id,
trait_item_def_id,
@ -645,7 +656,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
trait_item_def_id,
}) = origin
{
return self.infcx.report_extra_impl_obligation(
return self.report_extra_impl_obligation(
span,
impl_item_def_id,
trait_item_def_id,

View File

@ -17,14 +17,13 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
use rustc_span::{sym, Span};
use crate::error_reporting::TypeErrCtxt;
use crate::errors::{
ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
FunctionPointerSuggestion, SuggestAccessingField, SuggestRemoveSemiOrReturnBinding,
SuggestTuplePatternMany, SuggestTuplePatternOne, TypeErrorAdditionalDiags,
};
use super::TypeErrCtxt;
#[derive(Clone, Copy)]
pub enum SuggestAsRefKind {
Option,

View File

@ -1 +1,73 @@
use std::ops::Deref;
use rustc_errors::DiagCtxtHandle;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::PredicateObligation;
use rustc_macros::extension;
use rustc_middle::bug;
use rustc_middle::ty::{self, Ty};
use crate::error_reporting::infer::sub_relations;
pub mod infer;
pub mod traits;
/// A helper for building type related errors. The `typeck_results`
/// field is only populated during an in-progress typeck.
/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
///
/// You must only create this if you intend to actually emit an error (or
/// perhaps a warning, though preferably not.) It provides a lot of utility
/// methods which should not be used during the happy path.
pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'tcx>,
pub sub_relations: std::cell::RefCell<sub_relations::SubRelations>,
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
pub fallback_has_occurred: bool,
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
pub autoderef_steps:
Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
}
#[extension(pub trait InferCtxtErrorExt<'tcx>)]
impl<'tcx> InferCtxt<'tcx> {
/// Creates a `TypeErrCtxt` for emitting various inference errors.
/// During typeck, use `FnCtxt::err_ctxt` instead.
fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
TypeErrCtxt {
infcx: self,
sub_relations: Default::default(),
typeck_results: None,
fallback_has_occurred: false,
normalize_fn_sig: Box::new(|fn_sig| fn_sig),
autoderef_steps: Box::new(|ty| {
debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
vec![(ty, vec![])]
}),
}
}
}
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pub fn dcx(&self) -> DiagCtxtHandle<'a> {
self.infcx.dcx()
}
/// This is just to avoid a potential footgun of accidentally
/// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
#[deprecated(note = "you already have a `TypeErrCtxt`")]
#[allow(unused)]
pub fn err_ctxt(&self) -> ! {
bug!("called `err_ctxt` on `TypeErrCtxt`. Try removing the call");
}
}
impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> {
type Target = InferCtxt<'tcx>;
fn deref(&self) -> &InferCtxt<'tcx> {
self.infcx
}
}

View File

@ -8,21 +8,17 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor as _;
use rustc_hir::LangItem;
use rustc_infer::error_reporting::infer::TypeErrCtxt;
use rustc_infer::infer::need_type_info::TypeAnnotationNeeded;
use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt};
use rustc_infer::traits::util::elaborate;
use rustc_infer::traits::{
Obligation, ObligationCause, ObligationCauseCode, PolyTraitObligation, PredicateObligation,
};
use rustc_macros::extension;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable as _, TypeVisitableExt as _};
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
use crate::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
use crate::error_reporting::traits::{
to_pretty_impl_header, FindExprBySpan, InferCtxtPrivExt as _,
};
use crate::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use crate::error_reporting::traits::{to_pretty_impl_header, FindExprBySpan};
use crate::error_reporting::TypeErrCtxt;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::ObligationCtxt;
@ -153,10 +149,12 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
ambiguities
}
#[extension(pub trait TypeErrCtxtAmbiguityExt<'a, 'tcx>)]
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed {
pub(super) fn maybe_report_ambiguity(
&self,
obligation: &PredicateObligation<'tcx>,
) -> ErrorGuaranteed {
// Unable to successfully determine, probably means
// insufficient type information, but could mean
// ambiguous impls. The latter *ought* to be a

View File

@ -1,6 +1,9 @@
use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _};
use super::suggestions::{get_explanation_based_on_obligation, TypeErrCtxtExt as _};
use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote};
use super::suggestions::get_explanation_based_on_obligation;
use crate::error_reporting::infer::TyCategory;
use crate::error_reporting::traits::infer_ctxt_ext::InferCtxtExt;
use crate::error_reporting::traits::report_object_safety_error;
use crate::error_reporting::TypeErrCtxt;
use crate::errors::{
AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
};
@ -24,10 +27,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_hir::Node;
use rustc_hir::{self as hir, LangItem};
use rustc_infer::error_reporting::infer::TyCategory;
use rustc_infer::error_reporting::infer::TypeErrCtxt;
use rustc_infer::infer::{InferOk, TypeTrace};
use rustc_macros::extension;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::traits::SignatureMismatchData;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@ -49,14 +49,11 @@ use super::{
ArgKind, CandidateSimilarity, GetSafeTransmuteErrorAndReason, ImplCandidate, UnsatisfiedConst,
};
pub use rustc_infer::traits::error_reporting::*;
#[extension(pub trait TypeErrCtxtSelectionErrExt<'a, 'tcx>)]
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// The `root_obligation` parameter should be the `root_obligation` field
/// from a `FulfillmentError`. If no `FulfillmentError` is available,
/// then it should be the same as `obligation`.
fn report_selection_error(
pub fn report_selection_error(
&self,
mut obligation: PredicateObligation<'tcx>,
root_obligation: &PredicateObligation<'tcx>,
@ -682,9 +679,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
#[extension(pub(super) trait TypeErrCtxtExt<'a, 'tcx>)]
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn apply_do_not_recommend(&self, obligation: &mut PredicateObligation<'tcx>) -> bool {
pub(super) fn apply_do_not_recommend(
&self,
obligation: &mut PredicateObligation<'tcx>,
) -> bool {
let mut base_cause = obligation.cause.code().clone();
let mut applied_do_not_recommend = false;
loop {
@ -1142,7 +1141,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
#[extension(pub(super) trait InferCtxtPrivExt<'a, 'tcx>)]
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn can_match_trait(
&self,
@ -1182,7 +1180,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// returns if `cond` not occurring implies that `error` does not occur - i.e., that
// `error` occurring implies that `cond` occurs.
#[instrument(level = "debug", skip(self), ret)]
fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
pub(super) fn error_implies(
&self,
cond: ty::Predicate<'tcx>,
error: ty::Predicate<'tcx>,
) -> bool {
if cond == error {
return true;
}
@ -1205,7 +1207,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
#[instrument(level = "debug", skip_all)]
fn report_projection_error(
pub(super) fn report_projection_error(
&self,
obligation: &PredicateObligation<'tcx>,
error: &MismatchedProjectionTypes<'tcx>,
@ -1455,7 +1457,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn fuzzy_match_tys(
pub fn fuzzy_match_tys(
&self,
mut a: Ty<'tcx>,
mut b: Ty<'tcx>,
@ -1535,7 +1537,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str {
pub(super) fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str {
match kind {
hir::ClosureKind::Closure => "a closure",
hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) => "a coroutine",
@ -1585,7 +1587,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn find_similar_impl_candidates(
pub(super) fn find_similar_impl_candidates(
&self,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Vec<ImplCandidate<'tcx>> {
@ -1615,7 +1617,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
candidates
}
fn report_similar_impl_candidates(
pub(super) fn report_similar_impl_candidates(
&self,
impl_candidates: &[ImplCandidate<'tcx>],
trait_ref: ty::PolyTraitRef<'tcx>,
@ -1989,7 +1991,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// `trait_ref`.
///
/// For this to work, `new_self_ty` must have no escaping bound variables.
fn mk_trait_obligation_with_new_self_ty(
pub(super) fn mk_trait_obligation_with_new_self_ty(
&self,
param_env: ty::ParamEnv<'tcx>,
trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
@ -2041,7 +2043,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
})
}
fn note_obligation_cause(&self, err: &mut Diag<'_>, obligation: &PredicateObligation<'tcx>) {
pub fn note_obligation_cause(
&self,
err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>,
) {
// First, attempt to add note to this error with an async-await-specific
// message, and fall back to regular note otherwise.
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
@ -2067,7 +2073,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn is_recursive_obligation(
pub(super) fn is_recursive_obligation(
&self,
obligated_types: &mut Vec<Ty<'tcx>>,
cause_code: &ObligationCauseCode<'tcx>,

View File

@ -5,28 +5,24 @@ pub mod on_unimplemented;
mod overflow;
pub mod suggestions;
use std::iter;
use std::{fmt, iter};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_hir::def_id::DefId;
use rustc_errors::{struct_span_code_err, Applicability, Diag, MultiSpan, E0038, E0276};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_hir::{self as hir, LangItem};
use rustc_infer::error_reporting::infer::TypeErrCtxt;
use rustc_infer::traits::{
Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError,
ObjectSafetyViolation, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
SelectionError,
};
use rustc_macros::extension;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{ErrorGuaranteed, ExpnKind, Span};
use ambiguity::TypeErrCtxtAmbiguityExt as _;
use fulfillment_errors::TypeErrCtxtExt as _;
use suggestions::TypeErrCtxtExt as _;
use crate::error_reporting::TypeErrCtxt;
use crate::traits::{FulfillmentError, FulfillmentErrorCode};
pub use self::fulfillment_errors::*;
pub use self::infer_ctxt_ext::*;
pub use self::overflow::*;
@ -137,9 +133,8 @@ pub enum DefIdOrName {
Name(&'static str),
}
#[extension(pub trait TypeErrCtxtExt<'a, 'tcx>)]
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn report_fulfillment_errors(
pub fn report_fulfillment_errors(
&self,
mut errors: Vec<FulfillmentError<'tcx>>,
) -> ErrorGuaranteed {
@ -383,3 +378,194 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
w.push(';');
Some(w)
}
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pub fn report_extra_impl_obligation(
&self,
error_span: Span,
impl_item_def_id: LocalDefId,
trait_item_def_id: DefId,
requirement: &dyn fmt::Display,
) -> Diag<'a> {
let mut err = struct_span_code_err!(
self.dcx(),
error_span,
E0276,
"impl has stricter requirements than trait"
);
if !self.tcx.is_impl_trait_in_trait(trait_item_def_id) {
if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) {
let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
err.span_label(span, format!("definition of `{item_name}` from trait"));
}
}
err.span_label(error_span, format!("impl has extra requirement {requirement}"));
err
}
}
pub fn report_object_safety_error<'tcx>(
tcx: TyCtxt<'tcx>,
span: Span,
hir_id: Option<hir::HirId>,
trait_def_id: DefId,
violations: &[ObjectSafetyViolation],
) -> Diag<'tcx> {
let trait_str = tcx.def_path_str(trait_def_id);
let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node {
hir::Node::Item(item) => Some(item.ident.span),
_ => None,
});
let mut err = struct_span_code_err!(
tcx.dcx(),
span,
E0038,
"the trait `{}` cannot be made into an object",
trait_str
);
err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
if let Some(hir_id) = hir_id
&& let hir::Node::Ty(ty) = tcx.hir_node(hir_id)
&& let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
{
let mut hir_id = hir_id;
while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) {
hir_id = ty.hir_id;
}
if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
// Do not suggest `impl Trait` when dealing with things like super-traits.
err.span_suggestion_verbose(
ty.span.until(trait_ref.span),
"consider using an opaque type instead",
"impl ",
Applicability::MaybeIncorrect,
);
}
}
let mut reported_violations = FxIndexSet::default();
let mut multi_span = vec![];
let mut messages = vec![];
for violation in violations {
if let ObjectSafetyViolation::SizedSelf(sp) = &violation
&& !sp.is_empty()
{
// Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
// with a `Span`.
reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
}
if reported_violations.insert(violation.clone()) {
let spans = violation.spans();
let msg = if trait_span.is_none() || spans.is_empty() {
format!("the trait cannot be made into an object because {}", violation.error_msg())
} else {
format!("...because {}", violation.error_msg())
};
if spans.is_empty() {
err.note(msg);
} else {
for span in spans {
multi_span.push(span);
messages.push(msg.clone());
}
}
}
}
let has_multi_span = !multi_span.is_empty();
let mut note_span = MultiSpan::from_spans(multi_span.clone());
if let (Some(trait_span), true) = (trait_span, has_multi_span) {
note_span.push_span_label(trait_span, "this trait cannot be made into an object...");
}
for (span, msg) in iter::zip(multi_span, messages) {
note_span.push_span_label(span, msg);
}
err.span_note(
note_span,
"for a trait to be \"object safe\" it needs to allow building a vtable to allow the call \
to be resolvable dynamically; for more information visit \
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
);
// Only provide the help if its a local trait, otherwise it's not actionable.
if trait_span.is_some() {
let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
reported_violations.sort();
let mut potential_solutions: Vec<_> =
reported_violations.into_iter().map(|violation| violation.solution()).collect();
potential_solutions.sort();
// Allows us to skip suggesting that the same item should be moved to another trait multiple times.
potential_solutions.dedup();
for solution in potential_solutions {
solution.add_to(&mut err);
}
}
let impls_of = tcx.trait_impls_of(trait_def_id);
let impls = if impls_of.blanket_impls().is_empty() {
impls_of
.non_blanket_impls()
.values()
.flatten()
.filter(|def_id| {
!matches!(tcx.type_of(*def_id).instantiate_identity().kind(), ty::Dynamic(..))
})
.collect::<Vec<_>>()
} else {
vec![]
};
let externally_visible = if !impls.is_empty()
&& let Some(def_id) = trait_def_id.as_local()
// We may be executing this during typeck, which would result in cycle
// if we used effective_visibilities query, which looks into opaque types
// (and therefore calls typeck).
&& tcx.resolutions(()).effective_visibilities.is_exported(def_id)
{
true
} else {
false
};
match &impls[..] {
[] => {}
_ if impls.len() > 9 => {}
[only] if externally_visible => {
err.help(with_no_trimmed_paths!(format!(
"only type `{}` is seen to implement the trait in this crate, consider using it \
directly instead",
tcx.type_of(*only).instantiate_identity(),
)));
}
[only] => {
err.help(with_no_trimmed_paths!(format!(
"only type `{}` implements the trait, consider using it directly instead",
tcx.type_of(*only).instantiate_identity(),
)));
}
impls => {
let types = impls
.iter()
.map(|t| {
with_no_trimmed_paths!(format!(" {}", tcx.type_of(*t).instantiate_identity(),))
})
.collect::<Vec<_>>();
err.help(format!(
"the following types implement the trait, consider defining an enum where each \
variant holds one of these types, implementing `{}` for this new enum and using \
it instead:\n{}",
trait_str,
types.join("\n"),
));
}
}
if externally_visible {
err.note(format!(
"`{trait_str}` can be implemented in other crates; if you want to support your users \
passing their own types here, you can't refer to a specific type",
));
}
err
}

View File

@ -1,5 +1,5 @@
use super::{ObligationCauseCode, PredicateObligation};
use crate::error_reporting::traits::fulfillment_errors::InferCtxtPrivExt;
use crate::error_reporting::TypeErrCtxt;
use crate::errors::{
EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
};
@ -13,8 +13,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::error_reporting::infer::TypeErrCtxt;
use rustc_macros::{extension, LintDiagnostic};
use rustc_macros::LintDiagnostic;
use rustc_middle::bug;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::GenericArgsRef;
@ -41,7 +40,6 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
sym::Trait,
];
#[extension(pub trait TypeErrCtxtExt<'tcx>)]
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn impl_similar_to(
&self,
@ -109,7 +107,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
fn on_unimplemented_note(
pub fn on_unimplemented_note(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
obligation: &PredicateObligation<'tcx>,

View File

@ -5,17 +5,14 @@ use rustc_errors::{
};
use rustc_hir::def::Namespace;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_infer::error_reporting::infer::TypeErrCtxt;
use rustc_infer::traits::{Obligation, PredicateObligation};
use rustc_macros::extension;
use rustc_middle::ty::print::{FmtPrinter, Print};
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::Limit;
use rustc_span::Span;
use rustc_type_ir::Upcast;
use super::InferCtxtPrivExt;
use crate::error_reporting::traits::suggestions::TypeErrCtxtExt;
use crate::error_reporting::TypeErrCtxt;
pub enum OverflowCause<'tcx> {
DeeplyNormalize(ty::AliasTerm<'tcx>),
@ -38,7 +35,6 @@ pub fn suggest_new_overflow_limit<'tcx, G: EmissionGuarantee>(
));
}
#[extension(pub trait TypeErrCtxtOverflowExt<'a, 'tcx>)]
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// Reports that an overflow has occurred and halts compilation. We
/// halt compilation unconditionally because it is important that
@ -46,7 +42,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// whose result could not be truly determined and thus we can't say
/// if the program type checks or not -- and they are unusual
/// occurrences in any case.
fn report_overflow_error(
pub fn report_overflow_error(
&self,
cause: OverflowCause<'tcx>,
span: Span,
@ -59,7 +55,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
FatalError.raise();
}
fn build_overflow_error(
pub fn build_overflow_error(
&self,
cause: OverflowCause<'tcx>,
span: Span,
@ -132,7 +128,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// whose result could not be truly determined and thus we can't say
/// if the program type checks or not -- and they are unusual
/// occurrences in any case.
fn report_overflow_obligation<T>(
pub fn report_overflow_obligation<T>(
&self,
obligation: &Obligation<'tcx, T>,
suggest_increasing_limit: bool,
@ -165,7 +161,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// that we can give a more helpful error message (and, in particular,
/// we do not suggest increasing the overflow limit, which is not
/// going to help).
fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
pub fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
let cycle = self.resolve_vars_if_possible(cycle.to_owned());
assert!(!cycle.is_empty());
@ -179,7 +175,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
}
fn report_overflow_no_abort(
pub fn report_overflow_no_abort(
&self,
obligation: PredicateObligation<'tcx>,
suggest_increasing_limit: bool,

View File

@ -5,11 +5,10 @@ use super::{
PredicateObligation,
};
use crate::error_reporting::TypeErrCtxt;
use crate::errors;
use crate::infer::InferCtxt;
use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt};
use hir::def::CtorOf;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
@ -17,15 +16,15 @@ use rustc_errors::{
Style, SuggestionStyle,
};
use rustc_hir as hir;
use rustc_hir::def::CtorOf;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::is_range_literal;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node};
use rustc_infer::error_reporting::infer::TypeErrCtxt;
use rustc_infer::infer::InferCtxt;
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
use rustc_macros::extension;
use rustc_middle::hir::map;
use rustc_middle::traits::IsConstable;
use rustc_middle::ty::error::TypeError;
@ -44,7 +43,6 @@ use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::iter;
use crate::error_reporting::traits::fulfillment_errors::InferCtxtPrivExt;
use crate::infer::InferCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_middle::ty::print::{
@ -241,9 +239,8 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
}
}
#[extension(pub trait TypeErrCtxtExt<'a, 'tcx>)]
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
fn suggest_restricting_param_bound(
pub fn suggest_restricting_param_bound(
&self,
err: &mut Diag<'_>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
@ -453,7 +450,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// When after several dereferencing, the reference satisfies the trait
/// bound. This function provides dereference suggestion for this
/// specific situation.
fn suggest_dereferences(
pub(super) fn suggest_dereferences(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -782,7 +779,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// We tried to apply the bound to an `fn` or closure. Check whether calling it would
/// evaluate to a type that *would* satisfy the trait bound. If it would, suggest calling
/// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
fn suggest_fn_call(
pub(super) fn suggest_fn_call(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -898,7 +895,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
true
}
fn check_for_binding_assigned_block_without_tail_expression(
pub(super) fn check_for_binding_assigned_block_without_tail_expression(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -974,7 +971,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn suggest_add_clone_to_arg(
pub(super) fn suggest_add_clone_to_arg(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -1074,7 +1071,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// Extracts information about a callable type for diagnostics. This is a
/// heuristic -- it doesn't necessarily mean that a type is always callable,
/// because the callable type must also be well-formed to be called.
fn extract_callable_info(
pub fn extract_callable_info(
&self,
body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
@ -1200,7 +1197,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) }
}
fn suggest_add_reference_to_arg(
pub(super) fn suggest_add_reference_to_arg(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -1422,7 +1419,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
// Suggest borrowing the type
fn suggest_borrowing_for_object_cast(
pub(super) fn suggest_borrowing_for_object_cast(
&self,
err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>,
@ -1457,7 +1454,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
/// suggest removing these references until we reach a type that implements the trait.
fn suggest_remove_reference(
pub(super) fn suggest_remove_reference(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -1578,7 +1575,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
false
}
fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diag<'_>) {
pub(super) fn suggest_remove_await(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
) {
let hir = self.tcx.hir();
if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives()
&& let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id)
@ -1644,7 +1645,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// Check if the trait bound is implemented for a different mutability and note it in the
/// final error.
fn suggest_change_mut(
pub(super) fn suggest_change_mut(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -1720,7 +1721,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn suggest_semicolon_removal(
pub(super) fn suggest_semicolon_removal(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -1762,7 +1763,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
false
}
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
pub(super) fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. }) =
self.tcx.hir_node_by_def_id(obligation.cause.body_id)
else {
@ -1775,7 +1776,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
/// applicable and signal that the error has been expanded appropriately and needs to be
/// emitted.
fn suggest_impl_trait(
pub(super) fn suggest_impl_trait(
&self,
err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>,
@ -1865,7 +1866,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
true
}
fn point_at_returns_when_relevant(
pub(super) fn point_at_returns_when_relevant(
&self,
err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>,
@ -1897,7 +1898,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn report_closure_arg_mismatch(
pub(super) fn report_closure_arg_mismatch(
&self,
span: Span,
found_span: Option<Span>,
@ -2176,7 +2177,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn suggest_fully_qualified_path(
pub(super) fn suggest_fully_qualified_path(
&self,
err: &mut Diag<'_>,
item_def_id: DefId,
@ -2243,7 +2244,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
///
/// Returns `true` if an async-await specific note was added to the diagnostic.
#[instrument(level = "debug", skip_all, fields(?obligation.predicate, ?obligation.cause.span))]
fn maybe_note_obligation_cause_for_async_await<G: EmissionGuarantee>(
pub fn maybe_note_obligation_cause_for_async_await<G: EmissionGuarantee>(
&self,
err: &mut Diag<'_, G>,
obligation: &PredicateObligation<'tcx>,
@ -2712,7 +2713,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
}
fn note_obligation_cause_code<G: EmissionGuarantee, T>(
pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
&self,
body_id: LocalDefId,
err: &mut Diag<'_, G>,
@ -3554,7 +3555,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
#[instrument(
level = "debug", skip(self, err), fields(trait_pred.self_ty = ?trait_pred.self_ty())
)]
fn suggest_await_before_try(
pub(super) fn suggest_await_before_try(
&self,
err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>,
@ -3611,7 +3612,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn suggest_floating_point_literal(
pub(super) fn suggest_floating_point_literal(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -3635,7 +3636,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn suggest_derive(
pub fn suggest_derive(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -3701,7 +3702,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn suggest_dereferencing_index(
pub(super) fn suggest_dereferencing_index(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -4323,7 +4324,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// If the type that failed selection is an array or a reference to an array,
/// but the trait is implemented for slices, suggest that the user converts
/// the array into a slice.
fn suggest_convert_to_slice(
pub(super) fn suggest_convert_to_slice(
&self,
err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>,
@ -4395,7 +4396,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn explain_hrtb_projection(
pub(super) fn explain_hrtb_projection(
&self,
diag: &mut Diag<'_>,
pred: ty::PolyTraitPredicate<'tcx>,
@ -4461,7 +4462,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
fn suggest_desugaring_async_fn_in_trait(
pub(super) fn suggest_desugaring_async_fn_in_trait(
&self,
err: &mut Diag<'_>,
trait_ref: ty::PolyTraitRef<'tcx>,
@ -4545,7 +4546,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
}
fn ty_kind_suggestion(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> Option<String> {
pub fn ty_kind_suggestion(
&self,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<String> {
let tcx = self.infcx.tcx;
let implements_default = |ty| {
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
@ -4607,7 +4612,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
})
}
fn suggest_add_result_as_return_type(
pub(super) fn suggest_add_result_as_return_type(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>,
@ -4648,7 +4653,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
#[instrument(level = "debug", skip_all)]
fn suggest_unsized_bound_if_applicable(
pub(super) fn suggest_unsized_bound_if_applicable(
&self,
err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>,

File diff suppressed because it is too large Load Diff

View File

@ -173,7 +173,7 @@ impl Subdiagnostic for RegionExplanation<'_> {
diag.arg("desc_kind", self.desc.kind);
diag.arg("desc_arg", self.desc.arg);
let msg = f(diag, fluent::infer_region_explanation.into());
let msg = f(diag, fluent::trait_selection_region_explanation.into());
if let Some(span) = self.desc.span {
diag.span_note(span, msg);
} else {

View File

@ -22,11 +22,14 @@
#![feature(control_flow_enum)]
#![feature(extract_if)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(rustdoc_internals)]
#![feature(try_blocks)]
#![feature(type_alias_impl_trait)]
#![feature(unwrap_infallible)]
#![feature(yeet_expr)]
#![recursion_limit = "512"] // For rustdoc
// tidy-alphabetical-end

View File

@ -1,7 +1,8 @@
use std::fmt::Debug;
use std::marker::PhantomData;
use crate::error_reporting::traits::{OverflowCause, TypeErrCtxtOverflowExt};
use crate::error_reporting::traits::OverflowCause;
use crate::error_reporting::InferCtxtErrorExt;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
use rustc_data_structures::stack::ensure_sufficient_stack;

View File

@ -3,7 +3,7 @@ use std::fmt::Debug;
use super::{FromSolverError, TraitEngine};
use super::{FulfillmentContext, ScrubbedTraitError};
use crate::error_reporting::traits::TypeErrCtxtExt;
use crate::error_reporting::InferCtxtErrorExt;
use crate::regions::InferCtxtRegionExt;
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
use crate::solve::NextSolverError;

View File

@ -1,4 +1,3 @@
use crate::error_reporting::traits::TypeErrCtxtOverflowExt;
use crate::infer::{InferCtxt, TyOrConstInferVar};
use crate::traits::normalize::normalize_with_depth_to;
use rustc_data_structures::captures::Captures;
@ -25,6 +24,7 @@ use super::Unimplemented;
use super::{const_evaluatable, ScrubbedTraitError};
use super::{FulfillmentError, FulfillmentErrorCode};
use crate::error_reporting::InferCtxtErrorExt;
use crate::traits::project::PolyProjectionObligation;
use crate::traits::project::ProjectionCacheKeyExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt;

View File

@ -22,7 +22,7 @@ mod util;
pub mod vtable;
pub mod wf;
use crate::error_reporting::traits::TypeErrCtxtExt as _;
use crate::error_reporting::InferCtxtErrorExt;
use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::regions::InferCtxtRegionExt;

View File

@ -3,7 +3,7 @@
use super::SelectionContext;
use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
use crate::error_reporting::traits::OverflowCause;
use crate::error_reporting::traits::TypeErrCtxtOverflowExt;
use crate::error_reporting::InferCtxtErrorExt;
use crate::solve::NextSolverError;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::infer::at::At;

View File

@ -3,7 +3,7 @@
//! `normalize_canonicalized_projection_ty` query when it encounters projections.
use crate::error_reporting::traits::OverflowCause;
use crate::error_reporting::traits::TypeErrCtxtOverflowExt;
use crate::error_reporting::InferCtxtErrorExt;
use crate::infer::at::At;
use crate::infer::canonical::OriginalQueryValues;
use crate::infer::{InferCtxt, InferOk};

View File

@ -18,7 +18,7 @@ use super::{
TraitQueryMode,
};
use crate::error_reporting::traits::TypeErrCtxtOverflowExt;
use crate::error_reporting::InferCtxtErrorExt;
use crate::infer::{InferCtxt, InferCtxtExt, InferOk, TypeFreshener};
use crate::solve::InferCtxtSelectExt as _;
use crate::traits::normalize::normalize_with_depth;

View File

@ -7,7 +7,7 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::bug;
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtOverflowExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{
ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
Unimplemented,

View File

@ -2,7 +2,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtOverflowExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::{
normalize::NormalizationResult, CanonicalAliasGoal, NoSolution,

View File

@ -16,6 +16,7 @@ use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_must_use_ty;
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{return_ty, trait_ref_of_method};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use core::ops::ControlFlow;
@ -117,11 +118,11 @@ fn check_needless_must_use(
// Ignore async functions unless Future::Output type is a must_use type
if sig.header.is_async() {
let infcx = cx.tcx.infer_ctxt().build();
if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id))
if let Some(future_ty) = infcx.err_ctxt().get_impl_future_output_ty(return_ty(cx, item_id))
&& !is_must_use_ty(cx, future_ty)
{
return;
}
};
}
span_lint_and_help(

View File

@ -9,7 +9,7 @@ use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
declare_clippy_lint! {

View File

@ -15,6 +15,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
use rustc_span::Span;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use std::ops::Deref;
declare_clippy_lint! {
@ -159,7 +160,7 @@ impl NoEffect {
// Remove `impl Future<Output = T>` to get `T`
if cx.tcx.ty_is_opaque_future(ret_ty)
&& let Some(true_ret_ty) =
cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty)
cx.tcx.infer_ctxt().build().err_ctxt().get_impl_future_output_ty(ret_ty)
{
ret_ty = true_ret_ty;
}

View File

@ -3,7 +3,7 @@ error[E0308]: mismatched types
|
LL | const S: A = B;
| ^ expected `A`, found `B`
-Ztrack-diagnostics: created at compiler/rustc_infer/src/error_reporting/infer/mod.rs:LL:CC
-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
error: aborting due to 1 previous error

View File

@ -3,7 +3,7 @@ error[E0308]: mismatched types
|
LL | const S: A = B;
| ^ expected `A`, found `B`
-Ztrack-diagnostics: created at compiler/rustc_infer/src/error_reporting/infer/mod.rs:LL:CC
-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
error: aborting due to 1 previous error