Skip to content

[beta] backports #80560

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion compiler/rustc_infer/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ impl ProjectionCacheKey<'tcx> {
pub enum ProjectionCacheEntry<'tcx> {
InProgress,
Ambiguous,
Recur,
Error,
NormalizedTy(NormalizedTy<'tcx>),
}
Expand Down Expand Up @@ -143,7 +144,12 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
"ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
key, value
);
let fresh_key = self.map().insert(key, ProjectionCacheEntry::NormalizedTy(value));
let mut map = self.map();
if let Some(ProjectionCacheEntry::Recur) = map.get(&key) {
debug!("Not overwriting Recur");
return;
}
let fresh_key = map.insert(key, ProjectionCacheEntry::NormalizedTy(value));
assert!(!fresh_key, "never started projecting `{:?}`", key);
}

Expand Down Expand Up @@ -197,6 +203,14 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
assert!(!fresh, "never started projecting `{:?}`", key);
}

/// Indicates that while trying to normalize `key`, `key` was required to
/// be normalized again. Selection or evaluation should eventually report
/// an error here.
pub fn recur(&mut self, key: ProjectionCacheKey<'tcx>) {
let fresh = self.map().insert(key, ProjectionCacheEntry::Recur);
assert!(!fresh, "never started projecting `{:?}`", key);
}

/// Indicates that trying to normalize `key` resulted in
/// error.
pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
Expand Down
23 changes: 16 additions & 7 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,12 +496,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
return Ok(None);
}
Err(ProjectionCacheEntry::InProgress) => {
// If while normalized A::B, we are asked to normalize
// A::B, just return A::B itself. This is a conservative
// answer, in the sense that A::B *is* clearly equivalent
// to A::B, though there may be a better value we can
// find.

// Under lazy normalization, this can arise when
// bootstrapping. That is, imagine an environment with a
// where-clause like `A::B == u32`. Now, if we are asked
Expand All @@ -512,6 +506,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(

debug!("found cache entry: in-progress");

// Cache that normalizing this projection resulted in a cycle. This
// should ensure that, unless this happens within a snapshot that's
// rolled back, fulfillment or evaluation will notice the cycle.

infcx.inner.borrow_mut().projection_cache().recur(cache_key);
return Err(InProgress);
}
Err(ProjectionCacheEntry::Recur) => {
return Err(InProgress);
}
Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
Expand Down Expand Up @@ -734,7 +736,14 @@ fn project_type<'cx, 'tcx>(

if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
debug!("project: overflow!");
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
match selcx.query_mode() {
super::TraitQueryMode::Standard => {
selcx.infcx().report_overflow_error(&obligation, true);
}
super::TraitQueryMode::Canonical => {
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
}
}
}

let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx.tcx
}

pub(super) fn query_mode(&self) -> TraitQueryMode {
self.query_mode
}

///////////////////////////////////////////////////////////////////////////
// Selection
//
Expand Down
4 changes: 3 additions & 1 deletion library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1749,7 +1749,7 @@ struct WeakInner<'a> {
strong: &'a Cell<usize>,
}

impl<T: ?Sized> Weak<T> {
impl<T> Weak<T> {
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
Expand Down Expand Up @@ -1882,7 +1882,9 @@ impl<T: ?Sized> Weak<T> {
// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } }
}
}

impl<T: ?Sized> Weak<T> {
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
/// dropping of the inner value if successful.
///
Expand Down
24 changes: 0 additions & 24 deletions library/alloc/src/rc/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,30 +208,6 @@ fn into_from_weak_raw() {
}
}

#[test]
fn test_into_from_weak_raw_unsized() {
use std::fmt::Display;
use std::string::ToString;

let arc: Rc<str> = Rc::from("foo");
let weak: Weak<str> = Rc::downgrade(&arc);

let ptr = Weak::into_raw(weak.clone());
let weak2 = unsafe { Weak::from_raw(ptr) };

assert_eq!(unsafe { &*ptr }, "foo");
assert!(weak.ptr_eq(&weak2));

let arc: Rc<dyn Display> = Rc::new(123);
let weak: Weak<dyn Display> = Rc::downgrade(&arc);

let ptr = Weak::into_raw(weak.clone());
let weak2 = unsafe { Weak::from_raw(ptr) };

assert_eq!(unsafe { &*ptr }.to_string(), "123");
assert!(weak.ptr_eq(&weak2));
}

#[test]
fn get_mut() {
let mut x = Rc::new(3);
Expand Down
4 changes: 3 additions & 1 deletion library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1535,7 +1535,7 @@ struct WeakInner<'a> {
strong: &'a atomic::AtomicUsize,
}

impl<T: ?Sized> Weak<T> {
impl<T> Weak<T> {
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
Expand Down Expand Up @@ -1668,7 +1668,9 @@ impl<T: ?Sized> Weak<T> {
// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
unsafe { Weak { ptr: NonNull::new_unchecked(ptr) } }
}
}

impl<T: ?Sized> Weak<T> {
/// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying
/// dropping of the inner value if successful.
///
Expand Down
24 changes: 0 additions & 24 deletions library/alloc/src/sync/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,30 +158,6 @@ fn into_from_weak_raw() {
}
}

#[test]
fn test_into_from_weak_raw_unsized() {
use std::fmt::Display;
use std::string::ToString;

let arc: Arc<str> = Arc::from("foo");
let weak: Weak<str> = Arc::downgrade(&arc);

let ptr = Weak::into_raw(weak.clone());
let weak2 = unsafe { Weak::from_raw(ptr) };

assert_eq!(unsafe { &*ptr }, "foo");
assert!(weak.ptr_eq(&weak2));

let arc: Arc<dyn Display> = Arc::new(123);
let weak: Weak<dyn Display> = Arc::downgrade(&arc);

let ptr = Weak::into_raw(weak.clone());
let weak2 = unsafe { Weak::from_raw(ptr) };

assert_eq!(unsafe { &*ptr }.to_string(), "123");
assert!(weak.ptr_eq(&weak2));
}

#[test]
fn test_cowarc_clone_make_mut() {
let mut cow0 = Arc::new(75);
Expand Down
8 changes: 7 additions & 1 deletion src/bootstrap/tarball.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,16 @@ impl<'a> Tarball<'a> {
}

pub(crate) fn bare(self) -> PathBuf {
// Bare tarballs should have the top level directory match the package
// name, not "image". We rename the image directory just before passing
// into rust-installer.
let dest = self.temp_dir.join(self.package_name());
t!(std::fs::rename(&self.image_dir, &dest));

self.run(|this, cmd| {
cmd.arg("tarball")
.arg("--input")
.arg(&this.image_dir)
.arg(&dest)
.arg("--output")
.arg(crate::dist::distdir(this.builder).join(this.package_name()));
})
Expand Down
4 changes: 2 additions & 2 deletions src/stage0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# stable release's version number. `date` is the date where the release we're
# bootstrapping off was released.

date: 2020-12-29
date: 2020-12-31
rustc: 1.49.0

# We use a nightly rustfmt to format the source because it solves some
Expand All @@ -39,4 +39,4 @@ rustc: 1.49.0
# looking at a beta source tarball and it's uncommented we'll shortly comment it
# out.

dev: 1
#dev: 1
4 changes: 2 additions & 2 deletions src/test/ui/associated-types/defaults-cyclic-fail-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ impl Tr for u32 {
// ...but not in an impl that redefines one of the types.
impl Tr for bool {
type A = Box<Self::B>;
//~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
}
// (the error is shown twice for some reason)

impl Tr for usize {
type B = &'static Self::A;
//~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::A == _`
}

fn main() {
Expand Down
10 changes: 5 additions & 5 deletions src/test/ui/associated-types/defaults-cyclic-fail-1.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
--> $DIR/defaults-cyclic-fail-1.rs:26:5
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
--> $DIR/defaults-cyclic-fail-1.rs:32:5
|
LL | type B = &'static Self::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0275`.
4 changes: 2 additions & 2 deletions src/test/ui/associated-types/defaults-cyclic-fail-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ impl Tr for u32 {

impl Tr for bool {
type A = Box<Self::B>;
//~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
}
// (the error is shown twice for some reason)

impl Tr for usize {
type B = &'static Self::A;
//~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::A == _`
}

fn main() {
Expand Down
10 changes: 5 additions & 5 deletions src/test/ui/associated-types/defaults-cyclic-fail-2.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
--> $DIR/defaults-cyclic-fail-2.rs:27:5
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
--> $DIR/defaults-cyclic-fail-2.rs:33:5
|
LL | type B = &'static Self::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0275`.
29 changes: 29 additions & 0 deletions src/test/ui/associated-types/impl-wf-cycle-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Regression test for #79714

trait Baz {}
impl Baz for () {}
impl<T> Baz for (T,) {}

trait Fiz {}
impl Fiz for bool {}

trait Grault {
type A;
type B;
}

impl<T: Grault> Grault for (T,)
where
Self::A: Baz,
Self::B: Fiz,
{
type A = ();
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
type B = bool;
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
}
//~^^^^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`

fn main() {
let x: <(_,) as Grault>::A = ();
}
39 changes: 39 additions & 0 deletions src/test/ui/associated-types/impl-wf-cycle-1.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
--> $DIR/impl-wf-cycle-1.rs:15:1
|
LL | / impl<T: Grault> Grault for (T,)
LL | | where
LL | | Self::A: Baz,
LL | | Self::B: Fiz,
... |
LL | |
LL | | }
| |_^
|
= note: required because of the requirements on the impl of `Grault` for `(T,)`
= note: 1 redundant requirements hidden
= note: required because of the requirements on the impl of `Grault` for `(T,)`

error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
--> $DIR/impl-wf-cycle-1.rs:20:5
|
LL | type A = ();
| ^^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `Grault` for `(T,)`
= note: 1 redundant requirements hidden
= note: required because of the requirements on the impl of `Grault` for `(T,)`

error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
--> $DIR/impl-wf-cycle-1.rs:22:5
|
LL | type B = bool;
| ^^^^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `Grault` for `(T,)`
= note: 1 redundant requirements hidden
= note: required because of the requirements on the impl of `Grault` for `(T,)`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0275`.
16 changes: 16 additions & 0 deletions src/test/ui/associated-types/impl-wf-cycle-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Regression test for #79714

trait Grault {
type A;
}

impl<T: Grault> Grault for (T,)
where
Self::A: Copy,
{
type A = ();
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
}
//~^^^^^^^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`

fn main() {}
Loading