mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Rollup merge of #106170 - compiler-errors:autoderef-to-analysis, r=lcnr
Move autoderef to `rustc_hir_analysis` Not sure if this is a change we actually want, but autoderef really is only (functionally) used by `rustc_hir_analysis` and `rustc_hir_typeck`, so it probably should live there. Instead, implement a separate autoderef helper in `TypeErrCtxt` for the one use-case that goes against the ordering of the crate graph..
This commit is contained in:
commit
9928b14772
@ -120,3 +120,7 @@ hir_analysis_self_in_impl_self =
|
||||
|
||||
hir_analysis_linkage_type =
|
||||
invalid type for variable with `#[linkage]` attribute
|
||||
|
||||
hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
|
||||
.label = deref recursion limit reached
|
||||
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
|
||||
|
@ -2,10 +2,6 @@ trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entri
|
||||
|
||||
trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
|
||||
|
||||
trait_selection_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
|
||||
.label = deref recursion limit reached
|
||||
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
|
||||
|
||||
trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
|
||||
.label = empty on-clause here
|
||||
|
||||
|
@ -178,6 +178,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
||||
self.state.obligations
|
||||
}
|
||||
|
||||
pub fn current_obligations(&self) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||
self.state.obligations.clone()
|
||||
}
|
||||
|
||||
pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] {
|
||||
&self.state.steps
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
use crate::autoderef::Autoderef;
|
||||
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
|
||||
|
||||
use hir::def::DefKind;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||
@ -22,7 +24,6 @@ use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
|
@ -300,3 +300,15 @@ pub(crate) struct LinkageType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[help]
|
||||
#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = "E0055")]
|
||||
pub struct AutoDerefReachedRecursionLimit<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub ty: Ty<'a>,
|
||||
pub suggested_limit: rustc_session::Limit,
|
||||
pub crate_name: Symbol,
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ extern crate rustc_middle;
|
||||
pub mod check;
|
||||
|
||||
pub mod astconv;
|
||||
pub mod autoderef;
|
||||
mod bounds;
|
||||
mod check_unused;
|
||||
mod coherence;
|
||||
|
@ -2,11 +2,11 @@
|
||||
use super::method::MethodCallee;
|
||||
use super::{FnCtxt, PlaceOp};
|
||||
|
||||
use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
|
||||
|
||||
use std::iter;
|
||||
|
||||
|
@ -8,6 +8,7 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed,
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{self, CtorKind, Namespace, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir_analysis::autoderef::Autoderef;
|
||||
use rustc_infer::{
|
||||
infer,
|
||||
traits::{self, Obligation},
|
||||
@ -25,7 +26,6 @@ use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
|
@ -20,7 +20,7 @@ use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{self, Span};
|
||||
use rustc_span::{self, Span, DUMMY_SP};
|
||||
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
@ -175,6 +175,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
fn_sig
|
||||
})
|
||||
}),
|
||||
autoderef_steps: Box::new(|ty| {
|
||||
let mut autoderef = self.autoderef(DUMMY_SP, ty).silence_errors();
|
||||
let mut steps = vec![];
|
||||
while let Some((ty, _)) = autoderef.next() {
|
||||
steps.push((ty, autoderef.current_obligations()));
|
||||
}
|
||||
steps
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir_analysis::autoderef::{self, Autoderef};
|
||||
use rustc_infer::infer::canonical::OriginalQueryValues;
|
||||
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
@ -29,7 +30,6 @@ use rustc_span::lev_distance::{
|
||||
};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
|
||||
use rustc_trait_selection::autoderef::{self, Autoderef};
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
|
||||
use rustc_trait_selection::traits::query::method_autoderef::{
|
||||
|
@ -3,6 +3,7 @@ use crate::{has_expected_num_generic_args, FnCtxt, PlaceOp};
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir_analysis::autoderef::Autoderef;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast};
|
||||
@ -10,7 +11,6 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
use std::slice;
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
@ -55,6 +55,7 @@ use crate::infer::ExpectedFound;
|
||||
use crate::traits::error_reporting::report_object_safety_error;
|
||||
use crate::traits::{
|
||||
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
||||
PredicateObligation,
|
||||
};
|
||||
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
@ -91,8 +92,12 @@ pub mod nice_region_error;
|
||||
pub struct TypeErrCtxt<'a, 'tcx> {
|
||||
pub infcx: &'a InferCtxt<'tcx>,
|
||||
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
|
||||
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
|
||||
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 TypeErrCtxt<'_, '_> {
|
||||
|
@ -688,6 +688,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
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![])]
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_middle::ty::{self, PolyTraitRef, Ty};
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -21,18 +20,6 @@ pub struct UnableToConstructConstantValue<'a> {
|
||||
pub unevaluated: ty::UnevaluatedConst<'a>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[help]
|
||||
#[diag(trait_selection_auto_deref_reached_recursion_limit, code = "E0055")]
|
||||
pub struct AutoDerefReachedRecursionLimit<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub ty: Ty<'a>,
|
||||
pub suggested_limit: Limit,
|
||||
pub crate_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
|
||||
pub struct EmptyOnClauseInOnUnimplemented {
|
||||
|
@ -35,7 +35,6 @@ extern crate rustc_middle;
|
||||
#[macro_use]
|
||||
extern crate smallvec;
|
||||
|
||||
pub mod autoderef;
|
||||
pub mod errors;
|
||||
pub mod infer;
|
||||
pub mod solve;
|
||||
|
@ -5,7 +5,6 @@ use super::{
|
||||
PredicateObligation,
|
||||
};
|
||||
|
||||
use crate::autoderef::Autoderef;
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::traits::{NormalizeExt, ObligationCtxt};
|
||||
|
||||
@ -750,26 +749,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
|
||||
if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
|
||||
let mut autoderef = Autoderef::new(
|
||||
self,
|
||||
obligation.param_env,
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
base_ty,
|
||||
);
|
||||
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
|
||||
// Re-add the `&`
|
||||
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
|
||||
let autoderef = (self.autoderef_steps)(base_ty);
|
||||
if let Some(steps) =
|
||||
autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
|
||||
// Re-add the `&`
|
||||
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
|
||||
|
||||
// Remapping bound vars here
|
||||
let real_trait_pred_and_ty =
|
||||
real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
|
||||
let obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
real_trait_pred_and_ty,
|
||||
);
|
||||
Some(steps).filter(|_| self.predicate_may_hold(&obligation))
|
||||
}) {
|
||||
// Remapping bound vars here
|
||||
let real_trait_pred_and_ty =
|
||||
real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
|
||||
let obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
real_trait_pred_and_ty,
|
||||
);
|
||||
if obligations
|
||||
.iter()
|
||||
.chain([&obligation])
|
||||
.all(|obligation| self.predicate_may_hold(obligation))
|
||||
{
|
||||
Some(steps)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
{
|
||||
if steps > 0 {
|
||||
// Don't care about `&mut` because `DerefMut` is used less
|
||||
// often and user will not expect autoderef happens.
|
||||
|
Loading…
Reference in New Issue
Block a user