From e8c284ff2826e139fd77278af65a005a8b5b5bf3 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Fri, 14 May 2021 18:17:13 -0400 Subject: [PATCH 1/6] Make the UnifyValue for RegionVid () --- compiler/rustc_infer/src/infer/region_constraints/mod.rs | 7 +++---- compiler/rustc_middle/src/infer/unify_key.rs | 2 +- src/test/ui/traits/inductive-overflow/lifetime.rs | 2 ++ src/test/ui/traits/inductive-overflow/lifetime.stderr | 4 +++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 9ffcddfae9944..abbcff30cdaf2 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -3,7 +3,6 @@ use self::CombineMapType::*; use self::UndoLog::*; -use super::unify_key; use super::{ InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin, }; @@ -408,7 +407,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { if *any_unifications { *any_unifications = false; self.unification_table() - .reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid }); + .reset_unifications(|_| ()); } data @@ -435,7 +434,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { ) -> RegionVid { let vid = self.var_infos.push(RegionVariableInfo { origin, universe }); - let u_vid = self.unification_table().new_key(unify_key::RegionVidKey { min_vid: vid }); + let u_vid = self.unification_table().new_key(()); assert_eq!(vid, u_vid); self.undo_log.push(AddVar(vid)); debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin); @@ -618,7 +617,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } pub fn opportunistic_resolve_var(&mut self, rid: RegionVid) -> ty::RegionVid { - self.unification_table().probe_value(rid).min_vid + self.unification_table().find(rid) } fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> { diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 641cf23781e2c..8209e3db73965 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -38,7 +38,7 @@ impl UnifyValue for RegionVidKey { } impl UnifyKey for ty::RegionVid { - type Value = RegionVidKey; + type Value = (); fn index(&self) -> u32 { u32::from(*self) } diff --git a/src/test/ui/traits/inductive-overflow/lifetime.rs b/src/test/ui/traits/inductive-overflow/lifetime.rs index e23dfa57cd0d4..d66c30ed2dd7f 100644 --- a/src/test/ui/traits/inductive-overflow/lifetime.rs +++ b/src/test/ui/traits/inductive-overflow/lifetime.rs @@ -26,4 +26,6 @@ fn main() { // Should only be a few notes. is_send::>>(); //~^ ERROR overflow evaluating + //~^^ 2 redundant + //~^^^ required because of } diff --git a/src/test/ui/traits/inductive-overflow/lifetime.stderr b/src/test/ui/traits/inductive-overflow/lifetime.stderr index 752154b35cabe..cc91393039536 100644 --- a/src/test/ui/traits/inductive-overflow/lifetime.stderr +++ b/src/test/ui/traits/inductive-overflow/lifetime.stderr @@ -7,11 +7,13 @@ LL | fn is_send() {} LL | is_send::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | -note: required because of the requirements on the impl of `NotAuto` for `X>` +note: required because of the requirements on the impl of `NotAuto` for `X>` --> $DIR/lifetime.rs:19:12 | LL | impl NotAuto for X where T::P: NotAuto {} | ^^^^^^^ ^^^^ + = note: 2 redundant requirements hidden + = note: required because of the requirements on the impl of `NotAuto` for `X>` error: aborting due to previous error From 61157b341eab1b555cb5bd099e030817e6d41ba1 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Fri, 14 May 2021 21:48:32 -0400 Subject: [PATCH 2/6] Store Option as value for RegionVid --- .../src/infer/canonical/canonicalizer.rs | 26 ++++------ .../src/infer/region_constraints/mod.rs | 52 +++++++++++++------ compiler/rustc_infer/src/infer/resolve.rs | 18 +++---- compiler/rustc_infer/src/infer/undo_log.rs | 5 +- compiler/rustc_middle/src/infer/unify_key.rs | 52 +++++++++++-------- .../associated-types-eq-hr.rs | 2 + .../associated-types-eq-hr.stderr | 35 +++++++++++-- src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 2 +- src/test/ui/rfc1623.rs | 4 ++ src/test/ui/rfc1623.stderr | 39 +++++++++++++- .../ui/traits/inductive-overflow/lifetime.rs | 2 - .../traits/inductive-overflow/lifetime.stderr | 6 +-- .../ui/type-alias-impl-trait/issue-60371.rs | 2 +- .../type-alias-impl-trait/issue-60371.stderr | 7 ++- 14 files changed, 170 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index c68705da413f8..27ac817463f0e 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -304,6 +304,15 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + let tcx = self.tcx(); + let r = self + .infcx + .unwrap() + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_region(tcx, r); + match *r { ty::ReLateBound(index, ..) => { if index >= self.binder_index { @@ -313,22 +322,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { } } - ty::ReVar(vid) => { - let resolved_vid = self - .infcx - .unwrap() - .inner - .borrow_mut() - .unwrap_region_constraints() - .opportunistic_resolve_var(vid); - debug!( - "canonical: region var found with vid {:?}, \ - opportunistically resolved to {:?}", - vid, r - ); - let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid)); - self.canonicalize_region_mode.canonicalize_free_region(self, r) - } + ty::ReVar(_) => self.canonicalize_region_mode.canonicalize_free_region(self, r), ty::ReStatic | ty::ReEarlyBound(..) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index abbcff30cdaf2..dfbb82bd6576c 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -11,9 +11,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; -use rustc_data_structures::unify::UnifyKey; use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; +use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion}; use rustc_middle::ty::ReStatic; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ReLateBound, ReVar}; @@ -47,13 +47,13 @@ pub struct RegionConstraintStorage<'tcx> { /// When we add a R1 == R2 constriant, we currently add (a) edges /// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this - /// table. You can then call `opportunistic_resolve_var` early + /// table. You can then call `opportunistic_resolve_region` early /// which will map R1 and R2 to some common region (i.e., either /// R1 or R2). This is important when fulfillment, dropck and other such /// code is iterating to a fixed point, because otherwise we sometimes /// would wind up with a fresh stream of region variables that have been /// equated but appear distinct. - pub(super) unification_table: ut::UnificationTableStorage, + pub(super) unification_table: ut::UnificationTableStorage>, /// a flag set to true when we perform any unifications; this is used /// to micro-optimize `take_and_reset_data` @@ -406,8 +406,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { // `RegionConstraintData` contains the relationship here. if *any_unifications { *any_unifications = false; - self.unification_table() - .reset_unifications(|_| ()); + self.unification_table().reset_unifications(|_| UnifiedRegion(None)); } data @@ -434,8 +433,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { ) -> RegionVid { let vid = self.var_infos.push(RegionVariableInfo { origin, universe }); - let u_vid = self.unification_table().new_key(()); - assert_eq!(vid, u_vid); + let u_vid = self.unification_table().new_key(UnifiedRegion(None)); + assert_eq!(vid, u_vid.vid); self.undo_log.push(AddVar(vid)); debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin); vid @@ -497,10 +496,18 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { self.make_subregion(origin.clone(), sub, sup); self.make_subregion(origin, sup, sub); - if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) { - debug!("make_eqregion: uniying {:?} with {:?}", sub, sup); - self.unification_table().union(sub, sup); - self.any_unifications = true; + match (sub, sup) { + (&ty::ReVar(sub), &ty::ReVar(sup)) => { + debug!("make_eqregion: unifying {:?} with {:?}", sub, sup); + self.unification_table().union(sub, sup); + self.any_unifications = true; + } + (&ty::ReVar(vid), value) | (value, &ty::ReVar(vid)) => { + debug!("make_eqregion: unifying {:?} with {:?}", vid, value); + self.unification_table().union_value(vid, UnifiedRegion(Some(value))); + self.any_unifications = true; + } + (_, _) => {} } } } @@ -616,8 +623,21 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } } - pub fn opportunistic_resolve_var(&mut self, rid: RegionVid) -> ty::RegionVid { - self.unification_table().find(rid) + pub fn opportunistic_resolve_region( + &mut self, + tcx: TyCtxt<'tcx>, + region: ty::Region<'tcx>, + ) -> ty::Region<'tcx> { + match region { + ty::ReVar(rid) => { + let unified_region = self.unification_table().probe_value(*rid); + unified_region.0.unwrap_or_else(|| { + let root = self.unification_table().find(*rid).vid; + tcx.reuse_or_mk_region(region, ty::ReVar(root)) + }) + } + _ => region, + } } fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> { @@ -672,8 +692,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { &self, value_count: usize, ) -> (Range, Vec) { - let range = RegionVid::from_index(value_count as u32) - ..RegionVid::from_index(self.unification_table.len() as u32); + let range = RegionVid::from(value_count as u32) + ..RegionVid::from(self.unification_table.len() as u32); ( range.clone(), (range.start.index()..range.end.index()) @@ -695,7 +715,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } #[inline] - fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, ty::RegionVid> { + fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, RegionVidKey<'tcx>> { ut::UnificationTable::with_log(&mut self.storage.unification_table, self.undo_log) } } diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 48b8ee17594e3..4eec65b3d9618 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -84,18 +84,12 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - ty::ReVar(rid) => { - let resolved = self - .infcx - .inner - .borrow_mut() - .unwrap_region_constraints() - .opportunistic_resolve_var(rid); - self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved)) - } - _ => r, - } + let tcx = self.tcx(); + self.infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_region(tcx, r) } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index f41e872e00488..5ad2519a93c5f 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -3,6 +3,7 @@ use std::marker::PhantomData; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::undo_log::{Rollback, UndoLogs}; use rustc_data_structures::unify as ut; +use rustc_middle::infer::unify_key::RegionVidKey; use rustc_middle::ty; use crate::{ @@ -22,7 +23,7 @@ pub(crate) enum UndoLog<'tcx> { IntUnificationTable(sv::UndoLog>), FloatUnificationTable(sv::UndoLog>), RegionConstraintCollector(region_constraints::UndoLog<'tcx>), - RegionUnificationTable(sv::UndoLog>), + RegionUnificationTable(sv::UndoLog>>), ProjectionCache(traits::UndoLog<'tcx>), PushRegionObligation, } @@ -55,7 +56,7 @@ impl_from! { ConstUnificationTable(sv::UndoLog>>), - RegionUnificationTable(sv::UndoLog>), + RegionUnificationTable(sv::UndoLog>>), ProjectionCache(traits::UndoLog<'tcx>), } diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 8209e3db73965..2427b37f7419c 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -16,37 +16,45 @@ pub trait ToType { } #[derive(PartialEq, Copy, Clone, Debug)] -pub struct RegionVidKey { - /// The minimum region vid in the unification set. This is needed - /// to have a canonical name for a type to prevent infinite - /// recursion. - pub min_vid: ty::RegionVid, -} - -impl UnifyValue for RegionVidKey { - type Error = NoError; +pub struct UnifiedRegion<'tcx>(pub Option>); - fn unify_values(value1: &Self, value2: &Self) -> Result { - let min_vid = if value1.min_vid.index() < value2.min_vid.index() { - value1.min_vid - } else { - value2.min_vid - }; +#[derive(PartialEq, Copy, Clone, Debug)] +pub struct RegionVidKey<'tcx> { + pub vid: ty::RegionVid, + pub phantom: PhantomData>, +} - Ok(RegionVidKey { min_vid }) +impl<'tcx> From for RegionVidKey<'tcx> { + fn from(vid: ty::RegionVid) -> Self { + RegionVidKey { vid, phantom: PhantomData } } } -impl UnifyKey for ty::RegionVid { - type Value = (); +impl<'tcx> UnifyKey for RegionVidKey<'tcx> { + type Value = UnifiedRegion<'tcx>; fn index(&self) -> u32 { - u32::from(*self) + self.vid.as_u32() } - fn from_index(i: u32) -> ty::RegionVid { - ty::RegionVid::from(i) + fn from_index(i: u32) -> Self { + RegionVidKey::from(ty::RegionVid::from_u32(i)) } fn tag() -> &'static str { - "RegionVid" + "RegionVidKey" + } +} + +impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { + type Error = NoError; + + fn unify_values(value1: &Self, value2: &Self) -> Result { + Ok(match (value1.0, value2.0) { + (Some(_), Some(_)) => *value1, + + (Some(_), _) => *value1, + (_, Some(_)) => *value2, + + (None, None) => *value1, + }) } } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index fb391913c321e..2cf868f5280d0 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -102,6 +102,8 @@ pub fn call_tuple_two() { tuple_two::(); //~^ ERROR implementation of `TheTrait` is not general enough //~| ERROR implementation of `TheTrait` is not general enough + //~| ERROR mismatched types + //~| ERROR mismatched types } pub fn call_tuple_three() { diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 6897b31fe4685..281c3cf0fad85 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -46,6 +46,34 @@ LL | tuple_one::(); = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +error[E0308]: mismatched types + --> $DIR/associated-types-eq-hr.rs:102:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected reference `&'x isize` + found reference `&'y isize` +note: the lifetime requirement is introduced here + --> $DIR/associated-types-eq-hr.rs:66:53 + | +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/associated-types-eq-hr.rs:102:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected reference `&'x isize` + found reference `&'y isize` +note: the lifetime requirement is introduced here + --> $DIR/associated-types-eq-hr.rs:66:53 + | +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^ + error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:102:5 | @@ -65,7 +93,7 @@ LL | tuple_two::(); = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough - --> $DIR/associated-types-eq-hr.rs:112:5 + --> $DIR/associated-types-eq-hr.rs:114:5 | LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough @@ -73,6 +101,7 @@ LL | tuple_four::(); = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 7b81beeed4167..21feada38a865 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -9,7 +9,7 @@ LL | let v = Unit2.m( = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&u8,),)>>::Output == Unit3` +error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&'r u8,),)>>::Output == Unit3` --> $DIR/issue-62203-hrtb-ice.rs:38:19 | LL | let v = Unit2.m( diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index 9ff4813d11286..b74a141bade5c 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -23,6 +23,10 @@ static SOME_STRUCT: &SomeStruct = &SomeStruct { bar: &Bar { bools: &[true, true] }, f: &id, //~^ ERROR implementation of `FnOnce` is not general enough + //~^^ mismatched types + //~^^^ mismatched types + //~^^^^ mismatched types + //~^^^^^ mismatched types }; // very simple test for a 'static static with default lifetime diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index e95e68c8e6d26..67af4e045bbc5 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -1,3 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/rfc1623.rs:24:8 + | +LL | f: &id, + | ^^^ one type is more general than the other + | + = note: expected reference `&'a Foo<'b>` + found reference `&'a Foo<'b>` + +error[E0308]: mismatched types + --> $DIR/rfc1623.rs:24:8 + | +LL | f: &id, + | ^^^ one type is more general than the other + | + = note: expected reference `&'a Foo<'b>` + found reference `&'a Foo<'b>` + +error[E0308]: mismatched types + --> $DIR/rfc1623.rs:24:8 + | +LL | f: &id, + | ^^^ one type is more general than the other + | + = note: expected reference `&'a Foo<'b>` + found reference `&'a Foo<'b>` + +error[E0308]: mismatched types + --> $DIR/rfc1623.rs:24:8 + | +LL | f: &id, + | ^^^ one type is more general than the other + | + = note: expected reference `&'a Foo<'b>` + found reference `&'a Foo<'b>` + error: implementation of `FnOnce` is not general enough --> $DIR/rfc1623.rs:24:8 | @@ -7,5 +43,6 @@ LL | f: &id, = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` -error: aborting due to previous error +error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/traits/inductive-overflow/lifetime.rs b/src/test/ui/traits/inductive-overflow/lifetime.rs index d66c30ed2dd7f..e23dfa57cd0d4 100644 --- a/src/test/ui/traits/inductive-overflow/lifetime.rs +++ b/src/test/ui/traits/inductive-overflow/lifetime.rs @@ -26,6 +26,4 @@ fn main() { // Should only be a few notes. is_send::>>(); //~^ ERROR overflow evaluating - //~^^ 2 redundant - //~^^^ required because of } diff --git a/src/test/ui/traits/inductive-overflow/lifetime.stderr b/src/test/ui/traits/inductive-overflow/lifetime.stderr index cc91393039536..c739788352532 100644 --- a/src/test/ui/traits/inductive-overflow/lifetime.stderr +++ b/src/test/ui/traits/inductive-overflow/lifetime.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `Box>>: NotAuto` +error[E0275]: overflow evaluating the requirement `Box>>: NotAuto` --> $DIR/lifetime.rs:27:5 | LL | fn is_send() {} @@ -7,13 +7,11 @@ LL | fn is_send() {} LL | is_send::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | -note: required because of the requirements on the impl of `NotAuto` for `X>` +note: required because of the requirements on the impl of `NotAuto` for `X>` --> $DIR/lifetime.rs:19:12 | LL | impl NotAuto for X where T::P: NotAuto {} | ^^^^^^^ ^^^^ - = note: 2 redundant requirements hidden - = note: required because of the requirements on the impl of `NotAuto` for `X>` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs index 4ac7f9423ff41..959b637c850eb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs @@ -9,7 +9,7 @@ trait Bug { impl Bug for &() { type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable //~^ ERROR the trait bound `(): Bug` is not satisfied - //~^^ ERROR could not find defining uses + //~^^ ERROR the trait bound const FUN: fn() -> Self::Item = || (); //~^ ERROR type alias impl trait is not permitted here diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index 255d381bf0683..6857d5264b65e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -25,11 +25,14 @@ LL | type Item = impl Bug; = help: the following implementations were found: <&() as Bug> -error: could not find defining uses +error[E0277]: the trait bound `(): Bug` is not satisfied --> $DIR/issue-60371.rs:10:17 | LL | type Item = impl Bug; - | ^^^^^^^^ + | ^^^^^^^^ the trait `Bug` is not implemented for `()` + | + = help: the following implementations were found: + <&() as Bug> error: aborting due to 4 previous errors From fb6cec440a920c06eebea65c117dbc604899975e Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Sat, 15 May 2021 12:10:56 -0400 Subject: [PATCH 3/6] Revert to only using opportunistic_resolve_vars for existing places --- .../src/infer/canonical/canonicalizer.rs | 17 +++++++- .../src/infer/region_constraints/mod.rs | 7 +++- compiler/rustc_infer/src/infer/resolve.rs | 18 ++++++--- .../associated-types-eq-hr.rs | 2 - .../associated-types-eq-hr.stderr | 35 ++--------------- src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 2 +- src/test/ui/rfc1623.rs | 4 -- src/test/ui/rfc1623.stderr | 39 +------------------ .../ui/traits/inductive-overflow/lifetime.rs | 2 + .../traits/inductive-overflow/lifetime.stderr | 6 ++- .../ui/type-alias-impl-trait/issue-60371.rs | 2 +- .../type-alias-impl-trait/issue-60371.stderr | 7 +--- 12 files changed, 47 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 27ac817463f0e..337b8365d8cd5 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -322,7 +322,22 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { } } - ty::ReVar(_) => self.canonicalize_region_mode.canonicalize_free_region(self, r), + ty::ReVar(vid) => { + let resolved_vid = self + .infcx + .unwrap() + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(vid); + debug!( + "canonical: region var found with vid {:?}, \ + opportunistically resolved to {:?}", + vid, r + ); + let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid)); + self.canonicalize_region_mode.canonicalize_free_region(self, r) + } ty::ReStatic | ty::ReEarlyBound(..) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index dfbb82bd6576c..d46a91b6a77d8 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -623,6 +623,10 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } } + pub fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid { + self.unification_table().find(rid).vid + } + pub fn opportunistic_resolve_region( &mut self, tcx: TyCtxt<'tcx>, @@ -692,8 +696,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { &self, value_count: usize, ) -> (Range, Vec) { - let range = RegionVid::from(value_count as u32) - ..RegionVid::from(self.unification_table.len() as u32); + let range = RegionVid::from(value_count)..RegionVid::from(self.unification_table.len()); ( range.clone(), (range.start.index()..range.end.index()) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 4eec65b3d9618..48b8ee17594e3 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -84,12 +84,18 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - let tcx = self.tcx(); - self.infcx - .inner - .borrow_mut() - .unwrap_region_constraints() - .opportunistic_resolve_region(tcx, r) + match *r { + ty::ReVar(rid) => { + let resolved = self + .infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(rid); + self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved)) + } + _ => r, + } } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index 2cf868f5280d0..fb391913c321e 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -102,8 +102,6 @@ pub fn call_tuple_two() { tuple_two::(); //~^ ERROR implementation of `TheTrait` is not general enough //~| ERROR implementation of `TheTrait` is not general enough - //~| ERROR mismatched types - //~| ERROR mismatched types } pub fn call_tuple_three() { diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 281c3cf0fad85..6897b31fe4685 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -46,34 +46,6 @@ LL | tuple_one::(); = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error[E0308]: mismatched types - --> $DIR/associated-types-eq-hr.rs:102:5 - | -LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected reference `&'x isize` - found reference `&'y isize` -note: the lifetime requirement is introduced here - --> $DIR/associated-types-eq-hr.rs:66:53 - | -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ^^^^^^^^^^^^^ - -error[E0308]: mismatched types - --> $DIR/associated-types-eq-hr.rs:102:5 - | -LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected reference `&'x isize` - found reference `&'y isize` -note: the lifetime requirement is introduced here - --> $DIR/associated-types-eq-hr.rs:66:53 - | -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ^^^^^^^^^^^^^ - error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:102:5 | @@ -93,7 +65,7 @@ LL | tuple_two::(); = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough - --> $DIR/associated-types-eq-hr.rs:114:5 + --> $DIR/associated-types-eq-hr.rs:112:5 | LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough @@ -101,7 +73,6 @@ LL | tuple_four::(); = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0271, E0308. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr index 21feada38a865..7b81beeed4167 100644 --- a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr +++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr @@ -9,7 +9,7 @@ LL | let v = Unit2.m( = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&'r u8,),)>>::Output == Unit3` +error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&u8,),)>>::Output == Unit3` --> $DIR/issue-62203-hrtb-ice.rs:38:19 | LL | let v = Unit2.m( diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index b74a141bade5c..9ff4813d11286 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -23,10 +23,6 @@ static SOME_STRUCT: &SomeStruct = &SomeStruct { bar: &Bar { bools: &[true, true] }, f: &id, //~^ ERROR implementation of `FnOnce` is not general enough - //~^^ mismatched types - //~^^^ mismatched types - //~^^^^ mismatched types - //~^^^^^ mismatched types }; // very simple test for a 'static static with default lifetime diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index 67af4e045bbc5..e95e68c8e6d26 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -1,39 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/rfc1623.rs:24:8 - | -LL | f: &id, - | ^^^ one type is more general than the other - | - = note: expected reference `&'a Foo<'b>` - found reference `&'a Foo<'b>` - -error[E0308]: mismatched types - --> $DIR/rfc1623.rs:24:8 - | -LL | f: &id, - | ^^^ one type is more general than the other - | - = note: expected reference `&'a Foo<'b>` - found reference `&'a Foo<'b>` - -error[E0308]: mismatched types - --> $DIR/rfc1623.rs:24:8 - | -LL | f: &id, - | ^^^ one type is more general than the other - | - = note: expected reference `&'a Foo<'b>` - found reference `&'a Foo<'b>` - -error[E0308]: mismatched types - --> $DIR/rfc1623.rs:24:8 - | -LL | f: &id, - | ^^^ one type is more general than the other - | - = note: expected reference `&'a Foo<'b>` - found reference `&'a Foo<'b>` - error: implementation of `FnOnce` is not general enough --> $DIR/rfc1623.rs:24:8 | @@ -43,6 +7,5 @@ LL | f: &id, = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` -error: aborting due to 5 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/traits/inductive-overflow/lifetime.rs b/src/test/ui/traits/inductive-overflow/lifetime.rs index e23dfa57cd0d4..b75da1b512dc2 100644 --- a/src/test/ui/traits/inductive-overflow/lifetime.rs +++ b/src/test/ui/traits/inductive-overflow/lifetime.rs @@ -26,4 +26,6 @@ fn main() { // Should only be a few notes. is_send::>>(); //~^ ERROR overflow evaluating + //~| 2 redundant requirements hidden + //~| required because of } diff --git a/src/test/ui/traits/inductive-overflow/lifetime.stderr b/src/test/ui/traits/inductive-overflow/lifetime.stderr index c739788352532..cc91393039536 100644 --- a/src/test/ui/traits/inductive-overflow/lifetime.stderr +++ b/src/test/ui/traits/inductive-overflow/lifetime.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `Box>>: NotAuto` +error[E0275]: overflow evaluating the requirement `Box>>: NotAuto` --> $DIR/lifetime.rs:27:5 | LL | fn is_send() {} @@ -7,11 +7,13 @@ LL | fn is_send() {} LL | is_send::>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | -note: required because of the requirements on the impl of `NotAuto` for `X>` +note: required because of the requirements on the impl of `NotAuto` for `X>` --> $DIR/lifetime.rs:19:12 | LL | impl NotAuto for X where T::P: NotAuto {} | ^^^^^^^ ^^^^ + = note: 2 redundant requirements hidden + = note: required because of the requirements on the impl of `NotAuto` for `X>` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs index 959b637c850eb..4ac7f9423ff41 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs @@ -9,7 +9,7 @@ trait Bug { impl Bug for &() { type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable //~^ ERROR the trait bound `(): Bug` is not satisfied - //~^^ ERROR the trait bound + //~^^ ERROR could not find defining uses const FUN: fn() -> Self::Item = || (); //~^ ERROR type alias impl trait is not permitted here diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index 6857d5264b65e..255d381bf0683 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -25,14 +25,11 @@ LL | type Item = impl Bug; = help: the following implementations were found: <&() as Bug> -error[E0277]: the trait bound `(): Bug` is not satisfied +error: could not find defining uses --> $DIR/issue-60371.rs:10:17 | LL | type Item = impl Bug; - | ^^^^^^^^ the trait `Bug` is not implemented for `()` - | - = help: the following implementations were found: - <&() as Bug> + | ^^^^^^^^ error: aborting due to 4 previous errors From d2554776b81fa7dc966ee64f4ba88804a3e89322 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Sat, 15 May 2021 12:12:56 -0400 Subject: [PATCH 4/6] Add comment --- compiler/rustc_middle/src/infer/unify_key.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 2427b37f7419c..0b05dd5c0ba6f 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -48,6 +48,9 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { fn unify_values(value1: &Self, value2: &Self) -> Result { Ok(match (value1.0, value2.0) { + // Here we can just pick one value, because the full constraints graph + // will be handled later. Ideally, we might want a `MultipleValues` + // variant or something. For now though, this is fine. (Some(_), Some(_)) => *value1, (Some(_), _) => *value1, From 909d0e83d626151f54461e3819d31166b796b805 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Sat, 15 May 2021 12:26:50 -0400 Subject: [PATCH 5/6] Missed a couple things --- .../rustc_infer/src/infer/canonical/canonicalizer.rs | 9 --------- compiler/rustc_infer/src/infer/region_constraints/mod.rs | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 337b8365d8cd5..c68705da413f8 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -304,15 +304,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - let tcx = self.tcx(); - let r = self - .infcx - .unwrap() - .inner - .borrow_mut() - .unwrap_region_constraints() - .opportunistic_resolve_region(tcx, r); - match *r { ty::ReLateBound(index, ..) => { if index >= self.binder_index { diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index d46a91b6a77d8..69a33d46052ed 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -47,7 +47,7 @@ pub struct RegionConstraintStorage<'tcx> { /// When we add a R1 == R2 constriant, we currently add (a) edges /// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this - /// table. You can then call `opportunistic_resolve_region` early + /// table. You can then call `opportunistic_resolve_var` early /// which will map R1 and R2 to some common region (i.e., either /// R1 or R2). This is important when fulfillment, dropck and other such /// code is iterating to a fixed point, because otherwise we sometimes From c6e4284f8b786a700ca1a377c708a032240d34c8 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Sat, 15 May 2021 23:36:10 -0400 Subject: [PATCH 6/6] Add comments to opportunistic resolve functions --- compiler/rustc_infer/src/infer/region_constraints/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 69a33d46052ed..4935913016262 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -623,10 +623,14 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } } + /// Resolves the passed RegionVid to the root RegionVid in the unification table pub fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid { self.unification_table().find(rid).vid } + /// If the Region is a `ReVar`, then resolves it either to the root value in + /// the unification table, if it exists, or to the root `ReVar` in the table. + /// If the Region is not a `ReVar`, just returns the Region itself. pub fn opportunistic_resolve_region( &mut self, tcx: TyCtxt<'tcx>,