mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 05:53:10 +00:00
Auto merge of #119989 - lcnr:sub_relations-bye-bye, r=compiler-errors
remove `sub_relations` from the `InferCtxt` While doing so, I tried to remove the `delay_span_bug` in `rematch_impl` again, which lead me to discover another `freshen` bug, fixing that one in the second commit. See commit descriptions for the reasoning behind each change. r? `@compiler-errors`
This commit is contained in:
commit
397937d812
@ -1522,10 +1522,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if self.next_trait_solver()
|
||||
&& let ty::Alias(..) = ty.kind()
|
||||
{
|
||||
match self
|
||||
// We need to use a separate variable here as otherwise the temporary for
|
||||
// `self.fulfillment_cx.borrow_mut()` is alive in the `Err` branch, resulting
|
||||
// in a reentrant borrow, causing an ICE.
|
||||
let result = self
|
||||
.at(&self.misc(sp), self.param_env)
|
||||
.structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut())
|
||||
{
|
||||
.structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut());
|
||||
match result {
|
||||
Ok(normalized_ty) => normalized_ty,
|
||||
Err(errors) => {
|
||||
let guar = self.err_ctxt().report_fulfillment_errors(errors);
|
||||
|
@ -11,6 +11,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_infer::infer;
|
||||
use rustc_infer::infer::error_reporting::sub_relations::SubRelations;
|
||||
use rustc_infer::infer::error_reporting::TypeErrCtxt;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
@ -155,8 +156,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
///
|
||||
/// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt
|
||||
pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
|
||||
let mut sub_relations = SubRelations::default();
|
||||
sub_relations.add_constraints(
|
||||
self,
|
||||
self.fulfillment_cx.borrow_mut().pending_obligations().iter().map(|o| o.predicate),
|
||||
);
|
||||
TypeErrCtxt {
|
||||
infcx: &self.infcx,
|
||||
sub_relations: RefCell::new(sub_relations),
|
||||
typeck_results: Some(self.typeck_results.borrow()),
|
||||
fallback_has_occurred: self.fallback_has_occurred.get(),
|
||||
normalize_fn_sig: Box::new(|fn_sig| {
|
||||
|
@ -88,6 +88,7 @@ mod note_and_explain;
|
||||
mod suggest;
|
||||
|
||||
pub(crate) mod need_type_info;
|
||||
pub mod sub_relations;
|
||||
pub use need_type_info::TypeAnnotationNeeded;
|
||||
|
||||
pub mod nice_region_error;
|
||||
@ -123,6 +124,8 @@ fn escape_literal(s: &str) -> String {
|
||||
/// 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,
|
||||
|
||||
|
@ -502,7 +502,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
parent_name,
|
||||
});
|
||||
|
||||
let args = if self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn)
|
||||
let args = if self.tcx.get_diagnostic_item(sym::iterator_collect_fn)
|
||||
== Some(generics_def_id)
|
||||
{
|
||||
"Vec<_>".to_string()
|
||||
@ -710,7 +710,7 @@ struct InsertableGenericArgs<'tcx> {
|
||||
/// While doing so, the currently best spot is stored in `infer_source`.
|
||||
/// For details on how we rank spots, see [Self::source_cost]
|
||||
struct FindInferSourceVisitor<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
tecx: &'a TypeErrCtxt<'a, 'tcx>,
|
||||
typeck_results: &'a TypeckResults<'tcx>,
|
||||
|
||||
target: GenericArg<'tcx>,
|
||||
@ -722,12 +722,12 @@ struct FindInferSourceVisitor<'a, 'tcx> {
|
||||
|
||||
impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
fn new(
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
tecx: &'a TypeErrCtxt<'a, 'tcx>,
|
||||
typeck_results: &'a TypeckResults<'tcx>,
|
||||
target: GenericArg<'tcx>,
|
||||
) -> Self {
|
||||
FindInferSourceVisitor {
|
||||
infcx,
|
||||
tecx,
|
||||
typeck_results,
|
||||
|
||||
target,
|
||||
@ -778,7 +778,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// The sources are listed in order of preference here.
|
||||
let tcx = self.infcx.tcx;
|
||||
let tcx = self.tecx.tcx;
|
||||
let ctx = CostCtxt { tcx };
|
||||
match source.kind {
|
||||
InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty),
|
||||
@ -829,12 +829,12 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
|
||||
fn node_args_opt(&self, hir_id: HirId) -> Option<GenericArgsRef<'tcx>> {
|
||||
let args = self.typeck_results.node_args_opt(hir_id);
|
||||
self.infcx.resolve_vars_if_possible(args)
|
||||
self.tecx.resolve_vars_if_possible(args)
|
||||
}
|
||||
|
||||
fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
|
||||
let ty = self.typeck_results.node_type_opt(hir_id);
|
||||
self.infcx.resolve_vars_if_possible(ty)
|
||||
self.tecx.resolve_vars_if_possible(ty)
|
||||
}
|
||||
|
||||
// Check whether this generic argument is the inference variable we
|
||||
@ -849,7 +849,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
use ty::{Infer, TyVar};
|
||||
match (inner_ty.kind(), target_ty.kind()) {
|
||||
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
|
||||
self.infcx.inner.borrow_mut().type_variables().sub_unified(a_vid, b_vid)
|
||||
self.tecx.sub_relations.borrow_mut().unified(self.tecx, a_vid, b_vid)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
@ -857,12 +857,9 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
(GenericArgKind::Const(inner_ct), GenericArgKind::Const(target_ct)) => {
|
||||
use ty::InferConst::*;
|
||||
match (inner_ct.kind(), target_ct.kind()) {
|
||||
(ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.const_unification_table()
|
||||
.unioned(a_vid, b_vid),
|
||||
(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)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -917,7 +914,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
&self,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let tcx = self.tecx.tcx;
|
||||
match expr.kind {
|
||||
hir::ExprKind::Path(ref path) => {
|
||||
if let Some(args) = self.node_args_opt(expr.hir_id) {
|
||||
@ -980,7 +977,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
path: &'tcx hir::Path<'tcx>,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'a {
|
||||
let tcx = self.infcx.tcx;
|
||||
let tcx = self.tecx.tcx;
|
||||
let have_turbofish = path.segments.iter().any(|segment| {
|
||||
segment.args.is_some_and(|args| args.args.iter().any(|arg| arg.is_ty_or_const()))
|
||||
});
|
||||
@ -1034,7 +1031,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
args: GenericArgsRef<'tcx>,
|
||||
qpath: &'tcx hir::QPath<'tcx>,
|
||||
) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let tcx = self.tecx.tcx;
|
||||
match qpath {
|
||||
hir::QPath::Resolved(_self_ty, path) => {
|
||||
Box::new(self.resolved_path_inferred_arg_iter(path, args))
|
||||
@ -1107,7 +1104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
|
||||
type NestedFilter = nested_filter::OnlyBodies;
|
||||
|
||||
fn nested_visit_map(&mut self) -> Self::Map {
|
||||
self.infcx.tcx.hir()
|
||||
self.tecx.tcx.hir()
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, local: &'tcx Local<'tcx>) {
|
||||
@ -1163,7 +1160,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||
let tcx = self.infcx.tcx;
|
||||
let tcx = self.tecx.tcx;
|
||||
match expr.kind {
|
||||
// When encountering `func(arg)` first look into `arg` and then `func`,
|
||||
// as `arg` is "more specific".
|
||||
@ -1194,7 +1191,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
|
||||
if generics.parent.is_none() && generics.has_self {
|
||||
argument_index += 1;
|
||||
}
|
||||
let args = self.infcx.resolve_vars_if_possible(args);
|
||||
let args = self.tecx.resolve_vars_if_possible(args);
|
||||
let generic_args =
|
||||
&generics.own_args_no_defaults(tcx, args)[generics.own_counts().lifetimes..];
|
||||
let span = match expr.kind {
|
||||
@ -1224,7 +1221,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
|
||||
{
|
||||
let output = args.as_closure().sig().output().skip_binder();
|
||||
if self.generic_arg_contains_target(output.into()) {
|
||||
let body = self.infcx.tcx.hir().body(body);
|
||||
let body = self.tecx.tcx.hir().body(body);
|
||||
let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) {
|
||||
None
|
||||
} else {
|
||||
@ -1252,12 +1249,12 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
|
||||
&& let Some(args) = self.node_args_opt(expr.hir_id)
|
||||
&& args.iter().any(|arg| self.generic_arg_contains_target(arg))
|
||||
&& let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
|
||||
&& self.infcx.tcx.trait_of_item(def_id).is_some()
|
||||
&& self.tecx.tcx.trait_of_item(def_id).is_some()
|
||||
&& !has_impl_trait(def_id)
|
||||
{
|
||||
let successor =
|
||||
method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
|
||||
let args = self.infcx.resolve_vars_if_possible(args);
|
||||
let args = self.tecx.resolve_vars_if_possible(args);
|
||||
self.update_infer_source(InferSource {
|
||||
span: path.ident.span,
|
||||
kind: InferSourceKind::FullyQualifiedMethodCall {
|
||||
|
@ -0,0 +1,81 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::undo_log::NoUndo;
|
||||
use rustc_data_structures::unify as ut;
|
||||
use rustc_middle::ty;
|
||||
|
||||
use crate::infer::InferCtxt;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
struct SubId(u32);
|
||||
impl ut::UnifyKey for SubId {
|
||||
type Value = ();
|
||||
#[inline]
|
||||
fn index(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
#[inline]
|
||||
fn from_index(i: u32) -> SubId {
|
||||
SubId(i)
|
||||
}
|
||||
fn tag() -> &'static str {
|
||||
"SubId"
|
||||
}
|
||||
}
|
||||
|
||||
/// When reporting ambiguity errors, we sometimes want to
|
||||
/// treat all inference vars which are subtypes of each
|
||||
/// others as if they are equal. For this case we compute
|
||||
/// the transitive closure of our subtype obligations here.
|
||||
///
|
||||
/// E.g. when encountering ambiguity errors, we want to suggest
|
||||
/// specifying some method argument or to add a type annotation
|
||||
/// to a local variable. Because subtyping cannot change the
|
||||
/// shape of a type, it's fine if the cause of the ambiguity error
|
||||
/// is only related to the suggested variable via subtyping.
|
||||
///
|
||||
/// Even for something like `let x = returns_arg(); x.method();` the
|
||||
/// type of `x` is only a supertype of the argument of `returns_arg`. We
|
||||
/// still want to suggest specifying the type of the argument.
|
||||
#[derive(Default)]
|
||||
pub struct SubRelations {
|
||||
map: FxHashMap<ty::TyVid, SubId>,
|
||||
table: ut::UnificationTableStorage<SubId>,
|
||||
}
|
||||
|
||||
impl SubRelations {
|
||||
fn get_id<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, vid: ty::TyVid) -> SubId {
|
||||
let root_vid = infcx.root_var(vid);
|
||||
*self.map.entry(root_vid).or_insert_with(|| self.table.with_log(&mut NoUndo).new_key(()))
|
||||
}
|
||||
|
||||
pub fn add_constraints<'tcx>(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
obls: impl IntoIterator<Item = ty::Predicate<'tcx>>,
|
||||
) {
|
||||
for p in obls {
|
||||
let (a, b) = match p.kind().skip_binder() {
|
||||
ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
|
||||
(a, b)
|
||||
}
|
||||
ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => (a, b),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
match (a.kind(), b.kind()) {
|
||||
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
|
||||
let a = self.get_id(infcx, a_vid);
|
||||
let b = self.get_id(infcx, b_vid);
|
||||
self.table.with_log(&mut NoUndo).unify_var_var(a, b).unwrap();
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unified<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, a: ty::TyVid, b: ty::TyVid) -> bool {
|
||||
let a = self.get_id(infcx, a);
|
||||
let b = self.get_id(infcx, b);
|
||||
self.table.with_log(&mut NoUndo).unioned(a, b)
|
||||
}
|
||||
}
|
@ -56,49 +56,46 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn freshen_ty<F>(&mut self, opt_ty: Option<Ty<'tcx>>, key: ty::InferTy, mk_fresh: F) -> Ty<'tcx>
|
||||
fn freshen_ty<F>(&mut self, input: Result<Ty<'tcx>, ty::InferTy>, mk_fresh: F) -> Ty<'tcx>
|
||||
where
|
||||
F: FnOnce(u32) -> Ty<'tcx>,
|
||||
{
|
||||
if let Some(ty) = opt_ty {
|
||||
return ty.fold_with(self);
|
||||
}
|
||||
|
||||
match self.ty_freshen_map.entry(key) {
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
let index = self.ty_freshen_count;
|
||||
self.ty_freshen_count += 1;
|
||||
let t = mk_fresh(index);
|
||||
entry.insert(t);
|
||||
t
|
||||
}
|
||||
match input {
|
||||
Ok(ty) => ty.fold_with(self),
|
||||
Err(key) => match self.ty_freshen_map.entry(key) {
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
let index = self.ty_freshen_count;
|
||||
self.ty_freshen_count += 1;
|
||||
let t = mk_fresh(index);
|
||||
entry.insert(t);
|
||||
t
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn freshen_const<F>(
|
||||
&mut self,
|
||||
opt_ct: Option<ty::Const<'tcx>>,
|
||||
key: ty::InferConst,
|
||||
input: Result<ty::Const<'tcx>, ty::InferConst>,
|
||||
freshener: F,
|
||||
ty: Ty<'tcx>,
|
||||
) -> ty::Const<'tcx>
|
||||
where
|
||||
F: FnOnce(u32) -> ty::InferConst,
|
||||
{
|
||||
if let Some(ct) = opt_ct {
|
||||
return ct.fold_with(self);
|
||||
}
|
||||
|
||||
match self.const_freshen_map.entry(key) {
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
let index = self.const_freshen_count;
|
||||
self.const_freshen_count += 1;
|
||||
let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty);
|
||||
entry.insert(ct);
|
||||
ct
|
||||
}
|
||||
match input {
|
||||
Ok(ct) => ct.fold_with(self),
|
||||
Err(key) => match self.const_freshen_map.entry(key) {
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
let index = self.const_freshen_count;
|
||||
self.const_freshen_count += 1;
|
||||
let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty);
|
||||
entry.insert(ct);
|
||||
ct
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -146,19 +143,22 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
|
||||
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
|
||||
let opt_ct =
|
||||
self.infcx.inner.borrow_mut().const_unification_table().probe_value(v).known();
|
||||
self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty())
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let input =
|
||||
inner.const_unification_table().probe_value(v).known().ok_or_else(|| {
|
||||
ty::InferConst::Var(inner.const_unification_table().find(v).vid)
|
||||
});
|
||||
drop(inner);
|
||||
self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
|
||||
}
|
||||
ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
|
||||
let opt_ct =
|
||||
self.infcx.inner.borrow_mut().effect_unification_table().probe_value(v).known();
|
||||
self.freshen_const(
|
||||
opt_ct,
|
||||
ty::InferConst::EffectVar(v),
|
||||
ty::InferConst::Fresh,
|
||||
ct.ty(),
|
||||
)
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let input =
|
||||
inner.effect_unification_table().probe_value(v).known().ok_or_else(|| {
|
||||
ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid)
|
||||
});
|
||||
drop(inner);
|
||||
self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
|
||||
}
|
||||
ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
|
||||
if i >= self.const_freshen_count {
|
||||
@ -191,35 +191,37 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
|
||||
fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'tcx>> {
|
||||
match v {
|
||||
ty::TyVar(v) => {
|
||||
let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
|
||||
Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| Ty::new_fresh(self.infcx.tcx, n)))
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let input = inner
|
||||
.type_variables()
|
||||
.probe(v)
|
||||
.known()
|
||||
.ok_or_else(|| ty::TyVar(inner.type_variables().root_var(v)));
|
||||
drop(inner);
|
||||
Some(self.freshen_ty(input, |n| Ty::new_fresh(self.infcx.tcx, n)))
|
||||
}
|
||||
|
||||
ty::IntVar(v) => Some(
|
||||
self.freshen_ty(
|
||||
self.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.int_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx)),
|
||||
ty::IntVar(v),
|
||||
|n| Ty::new_fresh_int(self.infcx.tcx, n),
|
||||
),
|
||||
),
|
||||
ty::IntVar(v) => {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let input = inner
|
||||
.int_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx))
|
||||
.ok_or_else(|| ty::IntVar(inner.int_unification_table().find(v)));
|
||||
drop(inner);
|
||||
Some(self.freshen_ty(input, |n| Ty::new_fresh_int(self.infcx.tcx, n)))
|
||||
}
|
||||
|
||||
ty::FloatVar(v) => Some(
|
||||
self.freshen_ty(
|
||||
self.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.float_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx)),
|
||||
ty::FloatVar(v),
|
||||
|n| Ty::new_fresh_float(self.infcx.tcx, n),
|
||||
),
|
||||
),
|
||||
ty::FloatVar(v) => {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let input = inner
|
||||
.float_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.infcx.tcx))
|
||||
.ok_or_else(|| ty::FloatVar(inner.float_unification_table().find(v)));
|
||||
drop(inner);
|
||||
Some(self.freshen_ty(input, |n| Ty::new_fresh_float(self.infcx.tcx, n)))
|
||||
}
|
||||
|
||||
ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => {
|
||||
if ct >= self.ty_freshen_count {
|
||||
|
@ -762,6 +762,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
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),
|
||||
@ -1029,7 +1030,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
let r_b = self.shallow_resolve(predicate.skip_binder().b);
|
||||
match (r_a.kind(), r_b.kind()) {
|
||||
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
|
||||
self.inner.borrow_mut().type_variables().sub(a_vid, b_vid);
|
||||
return Err((a_vid, b_vid));
|
||||
}
|
||||
_ => {}
|
||||
|
@ -217,10 +217,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
) -> RelateResult<'tcx, Generalization<T>> {
|
||||
assert!(!source_term.has_escaping_bound_vars());
|
||||
let (for_universe, root_vid) = match target_vid.into() {
|
||||
ty::TermVid::Ty(ty_vid) => (
|
||||
self.probe_ty_var(ty_vid).unwrap_err(),
|
||||
ty::TermVid::Ty(self.inner.borrow_mut().type_variables().sub_root_var(ty_vid)),
|
||||
),
|
||||
ty::TermVid::Ty(ty_vid) => {
|
||||
(self.probe_ty_var(ty_vid).unwrap_err(), ty::TermVid::Ty(self.root_var(ty_vid)))
|
||||
}
|
||||
ty::TermVid::Const(ct_vid) => (
|
||||
self.probe_const_var(ct_vid).unwrap_err(),
|
||||
ty::TermVid::Const(
|
||||
@ -424,9 +423,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||
ty::Infer(ty::TyVar(vid)) => {
|
||||
let mut inner = self.infcx.inner.borrow_mut();
|
||||
let vid = inner.type_variables().root_var(vid);
|
||||
let sub_vid = inner.type_variables().sub_root_var(vid);
|
||||
|
||||
if ty::TermVid::Ty(sub_vid) == self.root_vid {
|
||||
if ty::TermVid::Ty(vid) == self.root_vid {
|
||||
// If sub-roots are equal, then `root_vid` and
|
||||
// `vid` are related via subtyping.
|
||||
Err(self.cyclic_term_error())
|
||||
@ -461,11 +458,6 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||
let new_var_id =
|
||||
inner.type_variables().new_var(self.for_universe, origin);
|
||||
let u = Ty::new_var(self.tcx(), new_var_id);
|
||||
|
||||
// Record that we replaced `vid` with `new_var_id` as part of a generalization
|
||||
// operation. This is needed to detect cyclic types. To see why, see the
|
||||
// docs in the `type_variables` module.
|
||||
inner.type_variables().sub(vid, new_var_id);
|
||||
debug!("replacing original vid={:?} with new={:?}", vid, u);
|
||||
Ok(u)
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use rustc_data_structures::undo_log::Rollback;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::ty::{self, Ty, TyVid};
|
||||
@ -12,35 +13,9 @@ use std::cmp;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Range;
|
||||
|
||||
use rustc_data_structures::undo_log::Rollback;
|
||||
|
||||
/// Represents a single undo-able action that affects a type inference variable.
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum UndoLog<'tcx> {
|
||||
EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
|
||||
SubRelation(sv::UndoLog<ut::Delegate<ty::TyVid>>),
|
||||
}
|
||||
|
||||
/// Convert from a specific kind of undo to the more general UndoLog
|
||||
impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
|
||||
fn from(l: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) -> Self {
|
||||
UndoLog::EqRelation(l)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert from a specific kind of undo to the more general UndoLog
|
||||
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
|
||||
fn from(l: sv::UndoLog<ut::Delegate<ty::TyVid>>) -> Self {
|
||||
UndoLog::SubRelation(l)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Rollback<UndoLog<'tcx>> for TypeVariableStorage<'tcx> {
|
||||
fn reverse(&mut self, undo: UndoLog<'tcx>) {
|
||||
match undo {
|
||||
UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
|
||||
UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo),
|
||||
}
|
||||
impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for TypeVariableStorage<'tcx> {
|
||||
fn reverse(&mut self, undo: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) {
|
||||
self.eq_relations.reverse(undo)
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,41 +27,6 @@ pub struct TypeVariableStorage<'tcx> {
|
||||
/// constraint `?X == ?Y`. This table also stores, for each key,
|
||||
/// the known value.
|
||||
eq_relations: ut::UnificationTableStorage<TyVidEqKey<'tcx>>,
|
||||
|
||||
/// Two variables are unified in `sub_relations` when we have a
|
||||
/// constraint `?X <: ?Y` *or* a constraint `?Y <: ?X`. This second
|
||||
/// table exists only to help with the occurs check. In particular,
|
||||
/// we want to report constraints like these as an occurs check
|
||||
/// violation:
|
||||
/// ``` text
|
||||
/// ?1 <: ?3
|
||||
/// Box<?3> <: ?1
|
||||
/// ```
|
||||
/// Without this second table, what would happen in a case like
|
||||
/// this is that we would instantiate `?1` with a generalized
|
||||
/// type like `Box<?6>`. We would then relate `Box<?3> <: Box<?6>`
|
||||
/// and infer that `?3 <: ?6`. Next, since `?1` was instantiated,
|
||||
/// we would process `?1 <: ?3`, generalize `?1 = Box<?6>` to `Box<?9>`,
|
||||
/// and instantiate `?3` with `Box<?9>`. Finally, we would relate
|
||||
/// `?6 <: ?9`. But now that we instantiated `?3`, we can process
|
||||
/// `?3 <: ?6`, which gives us `Box<?9> <: ?6`... and the cycle
|
||||
/// continues. (This is `occurs-check-2.rs`.)
|
||||
///
|
||||
/// What prevents this cycle is that when we generalize
|
||||
/// `Box<?3>` to `Box<?6>`, we also sub-unify `?3` and `?6`
|
||||
/// (in the generalizer). When we then process `Box<?6> <: ?3`,
|
||||
/// the occurs check then fails because `?6` and `?3` are sub-unified,
|
||||
/// and hence generalization fails.
|
||||
///
|
||||
/// This is reasonable because, in Rust, subtypes have the same
|
||||
/// "skeleton" and hence there is no possible type such that
|
||||
/// (e.g.) `Box<?3> <: ?3` for any `?3`.
|
||||
///
|
||||
/// In practice, we sometimes sub-unify variables in other spots, such
|
||||
/// as when processing subtype predicates. This is not necessary but is
|
||||
/// done to aid diagnostics, as it allows us to be more effective when
|
||||
/// we guide the user towards where they should insert type hints.
|
||||
sub_relations: ut::UnificationTableStorage<ty::TyVid>,
|
||||
}
|
||||
|
||||
pub struct TypeVariableTable<'a, 'tcx> {
|
||||
@ -158,7 +98,6 @@ impl<'tcx> TypeVariableStorage<'tcx> {
|
||||
TypeVariableStorage {
|
||||
values: Default::default(),
|
||||
eq_relations: ut::UnificationTableStorage::new(),
|
||||
sub_relations: ut::UnificationTableStorage::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,16 +136,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||
debug_assert!(self.probe(a).is_unknown());
|
||||
debug_assert!(self.probe(b).is_unknown());
|
||||
self.eq_relations().union(a, b);
|
||||
self.sub_relations().union(a, b);
|
||||
}
|
||||
|
||||
/// Records that `a <: b`, depending on `dir`.
|
||||
///
|
||||
/// Precondition: neither `a` nor `b` are known.
|
||||
pub fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
||||
debug_assert!(self.probe(a).is_unknown());
|
||||
debug_assert!(self.probe(b).is_unknown());
|
||||
self.sub_relations().union(a, b);
|
||||
}
|
||||
|
||||
/// Instantiates `vid` with the type `ty`.
|
||||
@ -240,10 +169,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||
origin: TypeVariableOrigin,
|
||||
) -> ty::TyVid {
|
||||
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
|
||||
|
||||
let sub_key = self.sub_relations().new_key(());
|
||||
debug_assert_eq!(eq_key.vid, sub_key);
|
||||
|
||||
let index = self.storage.values.push(TypeVariableData { origin });
|
||||
debug_assert_eq!(eq_key.vid, index);
|
||||
|
||||
@ -266,24 +191,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||
self.eq_relations().find(vid).vid
|
||||
}
|
||||
|
||||
/// Returns the "root" variable of `vid` in the `sub_relations`
|
||||
/// equivalence table. All type variables that have been are
|
||||
/// related via equality or subtyping will yield the same root
|
||||
/// variable (per the union-find algorithm), so `sub_root_var(a)
|
||||
/// == sub_root_var(b)` implies that:
|
||||
/// ```text
|
||||
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
|
||||
/// ```
|
||||
pub fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
|
||||
self.sub_relations().find(vid)
|
||||
}
|
||||
|
||||
/// Returns `true` if `a` and `b` have same "sub-root" (i.e., exists some
|
||||
/// type X such that `forall i in {a, b}. (i <: X || X <: i)`.
|
||||
pub fn sub_unified(&mut self, a: ty::TyVid, b: ty::TyVid) -> bool {
|
||||
self.sub_root_var(a) == self.sub_root_var(b)
|
||||
}
|
||||
|
||||
/// Retrieves the type to which `vid` has been instantiated, if
|
||||
/// any.
|
||||
pub fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
|
||||
@ -314,11 +221,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||
self.storage.eq_relations.with_log(self.undo_log)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, ty::TyVid> {
|
||||
self.storage.sub_relations.with_log(self.undo_log)
|
||||
}
|
||||
|
||||
/// Returns a range of the type variables created during the snapshot.
|
||||
pub fn vars_since_snapshot(
|
||||
&mut self,
|
||||
|
@ -20,7 +20,7 @@ pub struct Snapshot<'tcx> {
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum UndoLog<'tcx> {
|
||||
OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
|
||||
TypeVariables(type_variable::UndoLog<'tcx>),
|
||||
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
|
||||
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
|
||||
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
|
||||
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
|
||||
@ -46,17 +46,13 @@ macro_rules! impl_from {
|
||||
// Upcast from a single kind of "undoable action" to the general enum
|
||||
impl_from! {
|
||||
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
|
||||
TypeVariables(type_variable::UndoLog<'tcx>),
|
||||
|
||||
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
|
||||
TypeVariables(sv::UndoLog<ut::Delegate<ty::TyVid>>),
|
||||
|
||||
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
|
||||
|
||||
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
|
||||
EffectUnificationTable(sv::UndoLog<ut::Delegate<EffectVidKey<'tcx>>>),
|
||||
|
||||
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
|
||||
EffectUnificationTable(sv::UndoLog<ut::Delegate<EffectVidKey<'tcx>>>),
|
||||
|
||||
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
|
||||
ProjectionCache(traits::UndoLog<'tcx>),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||
use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt};
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
@ -60,8 +60,12 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
|
||||
let tcx = infcx.tcx;
|
||||
let recursion_limit = tcx.recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.depth) {
|
||||
let ty::Alias(_, data) = *alias_ty.kind() else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
self.at.infcx.err_ctxt().report_overflow_error(
|
||||
&alias_ty,
|
||||
OverflowCause::DeeplyNormalize(data),
|
||||
self.at.cause.span,
|
||||
true,
|
||||
|_| {},
|
||||
@ -109,7 +113,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
|
||||
let recursion_limit = tcx.recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.depth) {
|
||||
self.at.infcx.err_ctxt().report_overflow_error(
|
||||
&ty::Const::new_unevaluated(tcx, uv, ty),
|
||||
OverflowCause::DeeplyNormalize(ty::AliasTy::new(tcx, uv.def, uv.args)),
|
||||
self.at.cause.span,
|
||||
true,
|
||||
|_| {},
|
||||
|
@ -57,12 +57,21 @@ use super::{
|
||||
|
||||
pub use rustc_infer::traits::error_reporting::*;
|
||||
|
||||
pub enum OverflowCause<'tcx> {
|
||||
DeeplyNormalize(ty::AliasTy<'tcx>),
|
||||
TraitSolver(ty::Predicate<'tcx>),
|
||||
}
|
||||
|
||||
#[extension(pub trait TypeErrCtxtExt<'tcx>)]
|
||||
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
fn report_fulfillment_errors(
|
||||
&self,
|
||||
mut errors: Vec<FulfillmentError<'tcx>>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.sub_relations
|
||||
.borrow_mut()
|
||||
.add_constraints(self, errors.iter().map(|e| e.obligation.predicate));
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ErrorDescriptor<'tcx> {
|
||||
predicate: ty::Predicate<'tcx>,
|
||||
@ -180,49 +189,78 @@ impl<'tcx> TypeErrCtxt<'_, '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<T>(
|
||||
fn report_overflow_error(
|
||||
&self,
|
||||
predicate: &T,
|
||||
cause: OverflowCause<'tcx>,
|
||||
span: Span,
|
||||
suggest_increasing_limit: bool,
|
||||
mutate: impl FnOnce(&mut DiagnosticBuilder<'_>),
|
||||
) -> !
|
||||
where
|
||||
T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>,
|
||||
{
|
||||
let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit);
|
||||
) -> ! {
|
||||
let mut err = self.build_overflow_error(cause, span, suggest_increasing_limit);
|
||||
mutate(&mut err);
|
||||
err.emit();
|
||||
FatalError.raise();
|
||||
}
|
||||
|
||||
fn build_overflow_error<T>(
|
||||
fn build_overflow_error(
|
||||
&self,
|
||||
predicate: &T,
|
||||
cause: OverflowCause<'tcx>,
|
||||
span: Span,
|
||||
suggest_increasing_limit: bool,
|
||||
) -> DiagnosticBuilder<'tcx>
|
||||
where
|
||||
T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>,
|
||||
{
|
||||
let predicate = self.resolve_vars_if_possible(predicate.clone());
|
||||
let mut pred_str = predicate.to_string();
|
||||
|
||||
if pred_str.len() > 50 {
|
||||
// We don't need to save the type to a file, we will be talking about this type already
|
||||
// in a separate note when we explain the obligation, so it will be available that way.
|
||||
let mut cx: FmtPrinter<'_, '_> =
|
||||
FmtPrinter::new_with_limit(self.tcx, Namespace::TypeNS, rustc_session::Limit(6));
|
||||
predicate.print(&mut cx).unwrap();
|
||||
pred_str = cx.into_buffer();
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
fn with_short_path<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> String
|
||||
where
|
||||
T: fmt::Display + Print<'tcx, FmtPrinter<'tcx, 'tcx>>,
|
||||
{
|
||||
let s = value.to_string();
|
||||
if s.len() > 50 {
|
||||
// We don't need to save the type to a file, we will be talking about this type already
|
||||
// in a separate note when we explain the obligation, so it will be available that way.
|
||||
let mut cx: FmtPrinter<'_, '_> =
|
||||
FmtPrinter::new_with_limit(tcx, Namespace::TypeNS, rustc_session::Limit(6));
|
||||
value.print(&mut cx).unwrap();
|
||||
cx.into_buffer()
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0275,
|
||||
"overflow evaluating the requirement `{}`",
|
||||
pred_str,
|
||||
);
|
||||
|
||||
let mut err = match cause {
|
||||
OverflowCause::DeeplyNormalize(alias_ty) => {
|
||||
let alias_ty = self.resolve_vars_if_possible(alias_ty);
|
||||
let kind = alias_ty.opt_kind(self.tcx).map_or("alias", |k| k.descr());
|
||||
let alias_str = with_short_path(self.tcx, alias_ty);
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0275,
|
||||
"overflow normalizing the {kind} `{alias_str}`",
|
||||
)
|
||||
}
|
||||
OverflowCause::TraitSolver(predicate) => {
|
||||
let predicate = self.resolve_vars_if_possible(predicate);
|
||||
match predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ })
|
||||
| ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0275,
|
||||
"overflow assigning `{a}` to `{b}`",
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let pred_str = with_short_path(self.tcx, predicate);
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0275,
|
||||
"overflow evaluating the requirement `{pred_str}`",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if suggest_increasing_limit {
|
||||
self.suggest_new_overflow_limit(&mut err);
|
||||
@ -248,7 +286,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
let predicate = obligation.predicate.clone().to_predicate(self.tcx);
|
||||
let predicate = self.resolve_vars_if_possible(predicate);
|
||||
self.report_overflow_error(
|
||||
&predicate,
|
||||
OverflowCause::TraitSolver(predicate),
|
||||
obligation.cause.span,
|
||||
suggest_increasing_limit,
|
||||
|err| {
|
||||
@ -299,7 +337,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
|
||||
fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed {
|
||||
let obligation = self.resolve_vars_if_possible(obligation);
|
||||
let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true);
|
||||
let mut err = self.build_overflow_error(
|
||||
OverflowCause::TraitSolver(obligation.predicate),
|
||||
obligation.cause.span,
|
||||
true,
|
||||
);
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
self.point_at_returns_when_relevant(&mut err, &obligation);
|
||||
err.emit()
|
||||
|
@ -450,12 +450,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
.recursion_limit()
|
||||
.value_within_limit(obligation.recursion_depth) =>
|
||||
{
|
||||
self.selcx.infcx.err_ctxt().report_overflow_error(
|
||||
&obligation.predicate,
|
||||
obligation.cause.span,
|
||||
false,
|
||||
|_| {},
|
||||
);
|
||||
self.selcx.infcx.err_ctxt().report_overflow_obligation(&obligation, false);
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
|
@ -1,4 +1,8 @@
|
||||
//! Deeply normalize types using the old trait solver.
|
||||
use super::error_reporting::OverflowCause;
|
||||
use super::error_reporting::TypeErrCtxtExt;
|
||||
use super::SelectionContext;
|
||||
use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_infer::infer::at::At;
|
||||
use rustc_infer::infer::InferOk;
|
||||
@ -8,10 +12,6 @@ use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder};
|
||||
use rustc_middle::ty::{TypeFoldable, TypeSuperFoldable, TypeVisitable, TypeVisitableExt};
|
||||
|
||||
use super::error_reporting::TypeErrCtxtExt;
|
||||
use super::SelectionContext;
|
||||
use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
|
||||
|
||||
#[extension(pub trait NormalizeExt<'tcx>)]
|
||||
impl<'tcx> At<'_, 'tcx> {
|
||||
/// Normalize a value using the `AssocTypeNormalizer`.
|
||||
@ -173,7 +173,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
|
||||
}
|
||||
|
||||
let (kind, data) = match *ty.kind() {
|
||||
ty::Alias(kind, alias_ty) => (kind, alias_ty),
|
||||
ty::Alias(kind, data) => (kind, data),
|
||||
_ => return ty.super_fold_with(self),
|
||||
};
|
||||
|
||||
@ -210,7 +210,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
|
||||
let recursion_limit = self.interner().recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.depth) {
|
||||
self.selcx.infcx.err_ctxt().report_overflow_error(
|
||||
&ty,
|
||||
OverflowCause::DeeplyNormalize(data),
|
||||
self.cause.span,
|
||||
true,
|
||||
|_| {},
|
||||
@ -306,7 +306,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
|
||||
let recursion_limit = self.interner().recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.depth) {
|
||||
self.selcx.infcx.err_ctxt().report_overflow_error(
|
||||
&ty,
|
||||
OverflowCause::DeeplyNormalize(data),
|
||||
self.cause.span,
|
||||
false,
|
||||
|diag| {
|
||||
|
@ -5,6 +5,7 @@
|
||||
use crate::infer::at::At;
|
||||
use crate::infer::canonical::OriginalQueryValues;
|
||||
use crate::infer::{InferCtxt, InferOk};
|
||||
use crate::traits::error_reporting::OverflowCause;
|
||||
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||
use crate::traits::normalize::needs_normalization;
|
||||
use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
|
||||
@ -228,7 +229,11 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
|
||||
let guar = self
|
||||
.infcx
|
||||
.err_ctxt()
|
||||
.build_overflow_error(&ty, self.cause.span, true)
|
||||
.build_overflow_error(
|
||||
OverflowCause::DeeplyNormalize(data),
|
||||
self.cause.span,
|
||||
true,
|
||||
)
|
||||
.delay_as_bug();
|
||||
return Ok(Ty::new_error(self.interner(), guar));
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ use rustc_middle::dep_graph::DepNodeIndex;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::_match::MatchAgainstFreshVars;
|
||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::relate::TypeRelation;
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
|
||||
@ -2435,28 +2434,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
match self.match_impl(impl_def_id, impl_trait_header, obligation) {
|
||||
Ok(args) => args,
|
||||
Err(()) => {
|
||||
// FIXME: A rematch may fail when a candidate cache hit occurs
|
||||
// on the freshened form of the trait predicate, but the match
|
||||
// fails for some reason that is not captured in the freshened
|
||||
// cache key. For example, equating an impl trait ref against
|
||||
// the placeholder trait ref may fail due the Generalizer relation
|
||||
// raising a CyclicalTy error due to a sub_root_var relation
|
||||
// for a variable being generalized...
|
||||
let guar = self.infcx.dcx().span_delayed_bug(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"Impl {impl_def_id:?} was matchable against {obligation:?} but now is not"
|
||||
),
|
||||
);
|
||||
let value = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
|
||||
let err = Ty::new_error(self.tcx(), guar);
|
||||
let value = value.fold_with(&mut BottomUpFolder {
|
||||
tcx: self.tcx(),
|
||||
ty_op: |_| err,
|
||||
lt_op: |l| l,
|
||||
ct_op: |c| c,
|
||||
});
|
||||
Normalized { value, obligations: vec![] }
|
||||
let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
|
||||
bug!("impl {impl_def_id:?} was matchable against {predicate:?} but now is not")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +105,17 @@ pub enum AliasKind {
|
||||
Weak,
|
||||
}
|
||||
|
||||
impl AliasKind {
|
||||
pub fn descr(self) -> &'static str {
|
||||
match self {
|
||||
AliasKind::Projection => "associated type",
|
||||
AliasKind::Inherent => "inherent associated type",
|
||||
AliasKind::Opaque => "opaque type",
|
||||
AliasKind::Weak => "type alias",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines the kinds of types used by the type system.
|
||||
///
|
||||
/// Types written by the user start out as `hir::TyKind` and get
|
||||
|
@ -20,9 +20,10 @@ impl<T> Bind<T> for Foo<{ 6 + 1 }> {
|
||||
|
||||
fn main() {
|
||||
let (mut t, foo) = Foo::bind();
|
||||
//~^ ERROR mismatched types
|
||||
//~| NOTE cyclic type
|
||||
|
||||
// `t` is `ty::Infer(TyVar(?1t))`
|
||||
// `foo` contains `ty::Infer(TyVar(?1t))` in its substs
|
||||
t = foo;
|
||||
//~^ ERROR mismatched types
|
||||
//~| NOTE cyclic type
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/unused-substs-2.rs:25:9
|
||||
--> $DIR/unused-substs-2.rs:22:24
|
||||
|
|
||||
LL | t = foo;
|
||||
| ^^^ cyclic type of infinite size
|
||||
LL | let (mut t, foo) = Foo::bind();
|
||||
| ^^^^^^^^^^^ cyclic type of infinite size
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/unused-substs-5.rs:15:9
|
||||
--> $DIR/unused-substs-5.rs:15:19
|
||||
|
|
||||
LL | x = q::<_, N>(x);
|
||||
| ^^^^^^^^^^^^- help: try using a conversion method: `.to_vec()`
|
||||
| |
|
||||
| cyclic type of infinite size
|
||||
| ^ cyclic type of infinite size
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -3,6 +3,7 @@ use std::marker::PhantomData;
|
||||
fn _alias_check() {
|
||||
WrongImpl::foo(0i32);
|
||||
//~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
//~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
WrongImpl::<()>::foo(0i32);
|
||||
//~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
|
||||
//~| ERROR trait bounds were not satisfied
|
||||
|
@ -1,3 +1,18 @@
|
||||
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
--> $DIR/issue-62742.rs:4:5
|
||||
|
|
||||
LL | WrongImpl::foo(0i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
||||
|
|
||||
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
||||
note: required by a bound in `SafeImpl::<T, A>::foo`
|
||||
--> $DIR/issue-62742.rs:29:20
|
||||
|
|
||||
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
|
||||
| ^^^^^^ required by this bound in `SafeImpl::<T, A>::foo`
|
||||
LL | pub fn foo(value: A::Value) {}
|
||||
| --- required by a bound in this associated function
|
||||
|
||||
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||
--> $DIR/issue-62742.rs:4:5
|
||||
|
|
||||
@ -6,13 +21,13 @@ LL | WrongImpl::foo(0i32);
|
||||
|
|
||||
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
||||
note: required by a bound in `SafeImpl`
|
||||
--> $DIR/issue-62742.rs:26:35
|
||||
--> $DIR/issue-62742.rs:27:35
|
||||
|
|
||||
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
||||
| ^^^^^^ required by this bound in `SafeImpl`
|
||||
|
||||
error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-62742.rs:6:22
|
||||
--> $DIR/issue-62742.rs:7:22
|
||||
|
|
||||
LL | WrongImpl::<()>::foo(0i32);
|
||||
| ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds
|
||||
@ -24,20 +39,20 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
||||
| ----------------------------------------- function or associated item `foo` not found for this struct
|
||||
|
|
||||
note: trait bound `RawImpl<()>: Raw<()>` was not satisfied
|
||||
--> $DIR/issue-62742.rs:28:20
|
||||
--> $DIR/issue-62742.rs:29:20
|
||||
|
|
||||
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
|
||||
| ^^^^^^ --------------
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: the trait `Raw` must be implemented
|
||||
--> $DIR/issue-62742.rs:12:1
|
||||
--> $DIR/issue-62742.rs:13:1
|
||||
|
|
||||
LL | pub trait Raw<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
|
||||
--> $DIR/issue-62742.rs:6:5
|
||||
--> $DIR/issue-62742.rs:7:5
|
||||
|
|
||||
LL | WrongImpl::<()>::foo(0i32);
|
||||
| ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
|
||||
@ -45,12 +60,12 @@ LL | WrongImpl::<()>::foo(0i32);
|
||||
= help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
|
||||
= help: for that trait implementation, expected `[()]`, found `()`
|
||||
note: required by a bound in `SafeImpl`
|
||||
--> $DIR/issue-62742.rs:26:35
|
||||
--> $DIR/issue-62742.rs:27:35
|
||||
|
|
||||
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
||||
| ^^^^^^ required by this bound in `SafeImpl`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0599.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
@ -29,5 +29,5 @@ where
|
||||
}
|
||||
|
||||
fn main() {
|
||||
Race::new(|race| race.when()); //~ ERROR type annotations needed
|
||||
Race::new(|race| race.when()); //~ ERROR overflow assigning `_` to `Option<_>`
|
||||
}
|
||||
|
@ -1,14 +1,9 @@
|
||||
error[E0282]: type annotations needed for `RaceBuilder<T, Never<T>>`
|
||||
--> $DIR/issue-84073.rs:32:16
|
||||
error[E0275]: overflow assigning `_` to `Option<_>`
|
||||
--> $DIR/issue-84073.rs:32:22
|
||||
|
|
||||
LL | Race::new(|race| race.when());
|
||||
| ^^^^ ---- type must be known at this point
|
||||
|
|
||||
help: consider giving this closure parameter an explicit type, where the type for type parameter `T` is specified
|
||||
|
|
||||
LL | Race::new(|race: RaceBuilder<T, Never<T>>| race.when());
|
||||
| ++++++++++++++++++++++++++
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
@ -1,6 +1,3 @@
|
||||
//@ error-pattern: reached the recursion limit while auto-dereferencing
|
||||
//@ compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
struct Foo;
|
||||
@ -17,6 +14,7 @@ pub fn main() {
|
||||
let mut x;
|
||||
loop {
|
||||
x = Box::new(x);
|
||||
//~^ ERROR overflow assigning `Box<_>` to `_`
|
||||
x.foo;
|
||||
x.bar();
|
||||
}
|
||||
|
@ -1,54 +1,9 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/infinite-autoderef.rs:19:13
|
||||
error[E0275]: overflow assigning `Box<_>` to `_`
|
||||
--> $DIR/infinite-autoderef.rs:16:13
|
||||
|
|
||||
LL | x = Box::new(x);
|
||||
| ^^^^^^^^^^^ cyclic type of infinite size
|
||||
|
|
||||
help: consider unboxing the value
|
||||
|
|
||||
LL | x = *Box::new(x);
|
||||
| +
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
|
||||
--> $DIR/infinite-autoderef.rs:24:5
|
||||
|
|
||||
LL | Foo.foo;
|
||||
| ^^^^^^^ deref recursion limit reached
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`)
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
|
||||
--> $DIR/infinite-autoderef.rs:24:9
|
||||
|
|
||||
LL | Foo.foo;
|
||||
| ^^^ deref recursion limit reached
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`)
|
||||
|
||||
error[E0609]: no field `foo` on type `Foo`
|
||||
--> $DIR/infinite-autoderef.rs:24:9
|
||||
|
|
||||
LL | Foo.foo;
|
||||
| ^^^ unknown field
|
||||
|
||||
error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
|
||||
--> $DIR/infinite-autoderef.rs:25:9
|
||||
|
|
||||
LL | Foo.bar();
|
||||
| ^^^ deref recursion limit reached
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`)
|
||||
|
||||
error[E0599]: no method named `bar` found for struct `Foo` in the current scope
|
||||
--> $DIR/infinite-autoderef.rs:25:9
|
||||
|
|
||||
LL | struct Foo;
|
||||
| ---------- method `bar` not found for this struct
|
||||
...
|
||||
LL | Foo.bar();
|
||||
| ^^^ method not found in `Foo`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0055, E0308, E0599, E0609.
|
||||
For more information about an error, try `rustc --explain E0055`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0275]: overflow evaluating the requirement `X2`
|
||||
error[E0275]: overflow normalizing the type alias `X2`
|
||||
--> $DIR/infinite-type-alias-mutual-recursion.rs:6:11
|
||||
|
|
||||
LL | type X1 = X2;
|
||||
@ -6,7 +6,7 @@ LL | type X1 = X2;
|
||||
|
|
||||
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `X3`
|
||||
error[E0275]: overflow normalizing the type alias `X3`
|
||||
--> $DIR/infinite-type-alias-mutual-recursion.rs:9:11
|
||||
|
|
||||
LL | type X2 = X3;
|
||||
@ -14,7 +14,7 @@ LL | type X2 = X3;
|
||||
|
|
||||
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `X1`
|
||||
error[E0275]: overflow normalizing the type alias `X1`
|
||||
--> $DIR/infinite-type-alias-mutual-recursion.rs:11:11
|
||||
|
|
||||
LL | type X3 = X1;
|
||||
|
@ -5,10 +5,10 @@
|
||||
|
||||
type X1 = X2;
|
||||
//[gated]~^ ERROR cycle detected when expanding type alias `X1`
|
||||
//[feature]~^^ ERROR: overflow evaluating the requirement `X2`
|
||||
//[feature]~^^ ERROR: overflow normalizing the type alias `X2`
|
||||
type X2 = X3;
|
||||
//[feature]~^ ERROR: overflow evaluating the requirement `X3`
|
||||
//[feature]~^ ERROR: overflow normalizing the type alias `X3`
|
||||
type X3 = X1;
|
||||
//[feature]~^ ERROR: overflow evaluating the requirement `X1`
|
||||
//[feature]~^ ERROR: overflow normalizing the type alias `X1`
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0275]: overflow evaluating the requirement `X`
|
||||
error[E0275]: overflow normalizing the type alias `X`
|
||||
--> $DIR/infinite-vec-type-recursion.rs:6:10
|
||||
|
|
||||
LL | type X = Vec<X>;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
type X = Vec<X>;
|
||||
//[gated]~^ ERROR cycle detected
|
||||
//[feature]~^^ ERROR: overflow evaluating the requirement `X`
|
||||
//[feature]~^^ ERROR: overflow normalizing the type alias `X`
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn main() { let b: X = Vec::new(); }
|
||||
|
@ -18,6 +18,6 @@ fn main() {
|
||||
let f = |(_, _)| {};
|
||||
let g = |(a, _)| a;
|
||||
let t7 = |env| |a| |b| t7p(f, g)(((env, a), b));
|
||||
//~^ ERROR mismatched types
|
||||
let t8 = t8n(t7, t7p(f, g));
|
||||
//~^ ERROR: expected a `Fn(_)` closure, found `impl Fn(((_, _), _))` [E0277]
|
||||
}
|
||||
|
@ -1,18 +1,9 @@
|
||||
error[E0277]: expected a `Fn(_)` closure, found `impl Fn(((_, _), _))`
|
||||
--> $DIR/issue-59494.rs:21:22
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-59494.rs:20:40
|
||||
|
|
||||
LL | let t8 = t8n(t7, t7p(f, g));
|
||||
| --- ^^^^^^^^^ expected an `Fn(_)` closure, found `impl Fn(((_, _), _))`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))`
|
||||
note: required by a bound in `t8n`
|
||||
--> $DIR/issue-59494.rs:5:45
|
||||
|
|
||||
LL | fn t8n<A, B, C>(f: impl Fn(A) -> B, g: impl Fn(A) -> C) -> impl Fn(A) -> (B, C)
|
||||
| ^^^^^^^^^^ required by this bound in `t8n`
|
||||
LL | let t7 = |env| |a| |b| t7p(f, g)(((env, a), b));
|
||||
| ^^^ cyclic type of infinite size
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0275]: overflow evaluating the requirement `Loop`
|
||||
error[E0275]: overflow normalizing the type alias `Loop`
|
||||
--> $DIR/inherent-impls-overflow.rs:7:13
|
||||
|
|
||||
LL | type Loop = Loop;
|
||||
@ -6,7 +6,7 @@ LL | type Loop = Loop;
|
||||
|
|
||||
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `Loop`
|
||||
error[E0275]: overflow normalizing the type alias `Loop`
|
||||
--> $DIR/inherent-impls-overflow.rs:9:1
|
||||
|
|
||||
LL | impl Loop {}
|
||||
@ -14,24 +14,24 @@ LL | impl Loop {}
|
||||
|
|
||||
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `Poly0<((((((...,),),),),),)>`
|
||||
--> $DIR/inherent-impls-overflow.rs:11:17
|
||||
error[E0275]: overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
|
||||
--> $DIR/inherent-impls-overflow.rs:13:17
|
||||
|
|
||||
LL | type Poly0<T> = Poly1<(T,)>;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `Poly1<((((((...,),),),),),)>`
|
||||
--> $DIR/inherent-impls-overflow.rs:14:17
|
||||
error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
|
||||
--> $DIR/inherent-impls-overflow.rs:16:17
|
||||
|
|
||||
LL | type Poly1<T> = Poly0<(T,)>;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `Poly1<((((((...,),),),),),)>`
|
||||
--> $DIR/inherent-impls-overflow.rs:18:1
|
||||
error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
|
||||
--> $DIR/inherent-impls-overflow.rs:20:1
|
||||
|
|
||||
LL | impl Poly0<()> {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
@ -7,7 +7,7 @@ LL | impl Loop {}
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`)
|
||||
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/inherent-impls-overflow.rs:11:12
|
||||
--> $DIR/inherent-impls-overflow.rs:13:12
|
||||
|
|
||||
LL | type Poly0<T> = Poly1<(T,)>;
|
||||
| ^ unused type parameter
|
||||
@ -16,7 +16,7 @@ LL | type Poly0<T> = Poly1<(T,)>;
|
||||
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
|
||||
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/inherent-impls-overflow.rs:14:12
|
||||
--> $DIR/inherent-impls-overflow.rs:16:12
|
||||
|
|
||||
LL | type Poly1<T> = Poly0<(T,)>;
|
||||
| ^ unused type parameter
|
||||
@ -25,7 +25,7 @@ LL | type Poly1<T> = Poly0<(T,)>;
|
||||
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `Poly0<()> == _`
|
||||
--> $DIR/inherent-impls-overflow.rs:18:6
|
||||
--> $DIR/inherent-impls-overflow.rs:20:6
|
||||
|
|
||||
LL | impl Poly0<()> {}
|
||||
| ^^^^^^^^^
|
||||
|
@ -4,17 +4,21 @@
|
||||
#![feature(lazy_type_alias)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
type Loop = Loop; //[classic]~ ERROR overflow evaluating the requirement
|
||||
type Loop = Loop; //[classic]~ ERROR overflow normalizing the type alias `Loop`
|
||||
|
||||
impl Loop {} //~ ERROR overflow evaluating the requirement
|
||||
impl Loop {}
|
||||
//[classic]~^ ERROR overflow normalizing the type alias `Loop`
|
||||
//[next]~^^ ERROR overflow evaluating the requirement `Loop == _`
|
||||
|
||||
type Poly0<T> = Poly1<(T,)>;
|
||||
//[classic]~^ ERROR overflow evaluating the requirement
|
||||
//[classic]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
|
||||
//[next]~^^ ERROR type parameter `T` is never used
|
||||
type Poly1<T> = Poly0<(T,)>;
|
||||
//[classic]~^ ERROR overflow evaluating the requirement
|
||||
//[classic]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
|
||||
//[next]~^^ ERROR type parameter `T` is never used
|
||||
|
||||
impl Poly0<()> {} //~ ERROR overflow evaluating the requirement
|
||||
impl Poly0<()> {}
|
||||
//[classic]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
|
||||
//[next]~^^ ERROR overflow evaluating the requirement `Poly0<()> == _`
|
||||
|
||||
fn main() {}
|
||||
|
@ -5,6 +5,5 @@ fn main() {
|
||||
|
||||
g = f;
|
||||
f = Box::new(g);
|
||||
//~^ ERROR mismatched types
|
||||
//~| cyclic type of infinite size
|
||||
//~^ ERROR overflow assigning `Box<_>` to `_`
|
||||
}
|
||||
|
@ -1,14 +1,9 @@
|
||||
error[E0308]: mismatched types
|
||||
error[E0275]: overflow assigning `Box<_>` to `_`
|
||||
--> $DIR/occurs-check-2.rs:7:9
|
||||
|
|
||||
LL | f = Box::new(g);
|
||||
| ^^^^^^^^^^^ cyclic type of infinite size
|
||||
|
|
||||
help: consider unboxing the value
|
||||
|
|
||||
LL | f = *Box::new(g);
|
||||
| +
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
@ -1,5 +1,11 @@
|
||||
// From Issue #778
|
||||
|
||||
enum Clam<T> { A(T) }
|
||||
fn main() { let c; c = Clam::A(c); match c { Clam::A::<isize>(_) => { } } }
|
||||
//~^ ERROR mismatched types
|
||||
fn main() {
|
||||
let c;
|
||||
c = Clam::A(c);
|
||||
//~^ ERROR overflow assigning `Clam<_>` to `_`
|
||||
match c {
|
||||
Clam::A::<isize>(_) => { }
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/occurs-check-3.rs:4:24
|
||||
error[E0275]: overflow assigning `Clam<_>` to `_`
|
||||
--> $DIR/occurs-check-3.rs:6:9
|
||||
|
|
||||
LL | fn main() { let c; c = Clam::A(c); match c { Clam::A::<isize>(_) => { } } }
|
||||
| ^^^^^^^^^^ cyclic type of infinite size
|
||||
LL | c = Clam::A(c);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
@ -1,8 +1,5 @@
|
||||
fn main() {
|
||||
|
||||
let f;
|
||||
|
||||
f = Box::new(f);
|
||||
//~^ ERROR mismatched types
|
||||
//~| cyclic type of infinite size
|
||||
//~^ ERROR overflow assigning `Box<_>` to `_`
|
||||
}
|
||||
|
@ -1,14 +1,9 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/occurs-check.rs:5:9
|
||||
error[E0275]: overflow assigning `Box<_>` to `_`
|
||||
--> $DIR/occurs-check.rs:3:9
|
||||
|
|
||||
LL | f = Box::new(f);
|
||||
| ^^^^^^^^^^^ cyclic type of infinite size
|
||||
|
|
||||
help: consider unboxing the value
|
||||
|
|
||||
LL | f = *Box::new(f);
|
||||
| +
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
@ -13,10 +13,6 @@ fn main() {
|
||||
//~^ ERROR E0308
|
||||
test2(&y);
|
||||
//~^ ERROR E0308
|
||||
let f;
|
||||
f = Box::new(f);
|
||||
//~^ ERROR E0308
|
||||
|
||||
let s = &mut String::new();
|
||||
s = format!("foo");
|
||||
//~^ ERROR E0308
|
||||
|
@ -54,22 +54,11 @@ LL | fn test2(_x: &mut i32) {}
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/coerce-suggestions.rs:17:9
|
||||
|
|
||||
LL | f = Box::new(f);
|
||||
| ^^^^^^^^^^^ cyclic type of infinite size
|
||||
|
|
||||
help: consider unboxing the value
|
||||
|
|
||||
LL | f = *Box::new(f);
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/coerce-suggestions.rs:21:9
|
||||
|
|
||||
LL | s = format!("foo");
|
||||
| ^^^^^^^^^^^^^^ expected `&mut String`, found `String`
|
||||
|
|
||||
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -10,7 +10,7 @@ fn main() {
|
||||
let x = return;
|
||||
let y = return;
|
||||
let mut w = (x, y);
|
||||
//~^ ERROR overflow evaluating the requirement
|
||||
//~^ ERROR overflow assigning `_` to `*const _`
|
||||
// Avoid creating lifetimes, `Sized` bounds or function calls.
|
||||
let a = (ptr::addr_of!(y), ptr::addr_of!(x));
|
||||
w = a;
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0275]: overflow evaluating the requirement `_ <: *const _`
|
||||
error[E0275]: overflow assigning `_` to `*const _`
|
||||
--> $DIR/subtype-recursion-limit.rs:12:17
|
||||
|
|
||||
LL | let mut w = (x, y);
|
||||
|
@ -13,8 +13,8 @@ pub fn iso_un_option<A: 'static, B: 'static>(i: ISO<Option<A>, Option<B>>) -> IS
|
||||
//~^ ERROR no field `ab` on type
|
||||
//~| ERROR no field `ba` on type
|
||||
let left = move |o_a| match o_a {
|
||||
//~^ ERROR overflow evaluating the requirement
|
||||
None => panic!("absured"),
|
||||
//~^ ERROR overflow assigning `_` to `Option<_>`
|
||||
None => panic!("absurd"),
|
||||
Some(a) => a,
|
||||
};
|
||||
let right = move |o_b| match o_b {
|
||||
|
@ -10,7 +10,7 @@ error[E0609]: no field `ba` on type `(Box<(dyn Fn(Option<A>) -> Option<B> + 'sta
|
||||
LL | let (ab, ba) = (i.ab, i.ba);
|
||||
| ^^ unknown field
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `_ <: Option<_>`
|
||||
error[E0275]: overflow assigning `_` to `Option<_>`
|
||||
--> $DIR/well-formed-recursion-limit.rs:15:33
|
||||
|
|
||||
LL | let left = move |o_a| match o_a {
|
||||
|
Loading…
Reference in New Issue
Block a user