Skip to content

Commit

Permalink
Auto merge of #95250 - matthiaskrgr:rollup-ma4zl69, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #94249 (Better errors when a Copy impl on a Struct is not self-consistent)
 - #95069 (Fix auto traits in rustdoc)
 - #95221 (interpret/memory: simplify check_and_deref_ptr)
 - #95225 (remove `[async output]` from `impl Future` pretty-printing)
 - #95238 (Stop emitting E0026 for struct enums with underscores)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Mar 23, 2022
2 parents 9f4dc0b + fab7a6a commit 37b55c8
Show file tree
Hide file tree
Showing 34 changed files with 203 additions and 66 deletions.
20 changes: 5 additions & 15 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,22 +427,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
}
}

// Extract from the pointer an `Option<AllocId>` and an offset, which is relative to the
// allocation or (if that is `None`) an absolute address.
let ptr_or_addr = if size.bytes() == 0 {
// Let's see what we can do, but don't throw errors if there's nothing there.
self.ptr_try_get_alloc(ptr)
} else {
// A "real" access, we insist on getting an `AllocId`.
Ok(self.ptr_get_alloc(ptr)?)
};
Ok(match ptr_or_addr {
Ok(match self.ptr_try_get_alloc(ptr) {
Err(addr) => {
// No memory is actually being accessed.
debug_assert!(size.bytes() == 0);
// Must be non-null.
if addr == 0 {
throw_ub!(DanglingIntPointer(0, msg))
// We couldn't get a proper allocation. This is only okay if the access size is 0,
// and the address is not null.
if size.bytes() > 0 || addr == 0 {
throw_ub!(DanglingIntPointer(addr, msg));
}
// Must be aligned.
if let Some(align) = align {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#![feature(new_uninit)]
#![feature(nll)]
#![feature(once_cell)]
#![feature(let_chains)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(trusted_len)]
Expand Down
36 changes: 20 additions & 16 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,44 +896,48 @@ pub trait PrettyPrinter<'tcx>:
);

if !generics.is_empty() || !assoc_items.is_empty() {
p!("<");
let mut first = true;

for ty in generics {
if !first {
if first {
p!("<");
first = false;
} else {
p!(", ");
}
p!(print(trait_ref.rebind(*ty)));
first = false;
}

for (assoc_item_def_id, term) in assoc_items {
if !first {
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks
if let Some(ty) = term.skip_binder().ty() &&
let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = ty.kind() &&
Some(*item_def_id) == self.tcx().lang_items().generator_return() {
continue;
}

if first {
p!("<");
first = false;
} else {
p!(", ");
}

p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).name));

match term.skip_binder() {
Term::Ty(ty) => {
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks
if matches!(
ty.kind(), ty::Projection(ty::ProjectionTy { item_def_id, .. })
if Some(*item_def_id) == self.tcx().lang_items().generator_return()
) {
p!("[async output]")
} else {
p!(print(ty))
}
p!(print(ty))
}
Term::Const(c) => {
p!(print(c));
}
};

first = false;
}

p!(">");
if !first {
p!(">");
}
}

first = false;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::traits::error_reporting::InferCtxtExt;

#[derive(Clone)]
pub enum CopyImplementationError<'tcx> {
InfrigingFields(Vec<&'tcx ty::FieldDef>),
InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>)>),
NotAnAdt,
HasDestructor,
}
Expand Down Expand Up @@ -67,7 +67,7 @@ pub fn can_type_implement_copy<'tcx>(
match traits::fully_normalize(&infcx, ctx, cause, param_env, ty) {
Ok(ty) => {
if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
infringing.push(field);
infringing.push((field, ty));
}
}
Err(errors) => {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1270,7 +1270,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// the master cache. Since coherence executes pretty quickly,
// it's not worth going to more trouble to increase the
// hit-rate, I don't think.
if self.intercrate {
if self.intercrate || self.allow_negative_impls {
return false;
}

Expand All @@ -1287,7 +1287,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// mode, so don't do any caching. In particular, we might
// re-use the same `InferCtxt` with both an intercrate
// and non-intercrate `SelectionContext`
if self.intercrate {
if self.intercrate || self.allow_negative_impls {
return None;
}
let tcx = self.tcx();
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_typeck/src/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::{sym, Ident};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, MultiSpan, DUMMY_SP};
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::traits::{ObligationCause, Pattern};
Expand Down Expand Up @@ -1275,7 +1275,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.filter(|(_, ident)| !used_fields.contains_key(ident))
.collect::<Vec<_>>();

let inexistent_fields_err = if !(inexistent_fields.is_empty() || variant.is_recovered()) {
let inexistent_fields_err = if !(inexistent_fields.is_empty() || variant.is_recovered())
&& !inexistent_fields.iter().any(|field| field.name == kw::Underscore)
{
Some(self.error_inexistent_fields(
adt.variant_descr(),
&inexistent_fields,
Expand Down
36 changes: 34 additions & 2 deletions compiler/rustc_typeck/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,40 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
E0204,
"the trait `Copy` may not be implemented for this type"
);
for span in fields.iter().map(|f| tcx.def_span(f.did)) {
err.span_label(span, "this field does not implement `Copy`");
for (field, ty) in fields {
let field_span = tcx.def_span(field.did);
err.span_label(field_span, "this field does not implement `Copy`");
// Spin up a new FulfillmentContext, so we can get the _precise_ reason
// why this field does not implement Copy. This is useful because sometimes
// it is not immediately clear why Copy is not implemented for a field, since
// all we point at is the field itself.
tcx.infer_ctxt().enter(|infcx| {
let mut fulfill_cx = traits::FulfillmentContext::new_ignoring_regions();
fulfill_cx.register_bound(
&infcx,
param_env,
ty,
tcx.lang_items().copy_trait().unwrap(),
traits::ObligationCause::dummy_with_span(field_span),
);
for error in fulfill_cx.select_all_or_error(&infcx) {
let error_predicate = error.obligation.predicate;
// Only note if it's not the root obligation, otherwise it's trivial and
// should be self-explanatory (i.e. a field literally doesn't implement Copy).

// FIXME: This error could be more descriptive, especially if the error_predicate
// contains a foreign type or if it's a deeply nested type...
if error_predicate != error.root_obligation.predicate {
err.span_note(
error.obligation.cause.span,
&format!(
"the `Copy` impl for `{}` requires that `{}`",
ty, error_predicate
),
);
}
}
});
}
err.emit();
}
Expand Down
8 changes: 8 additions & 0 deletions src/test/rustdoc/auto-trait-not-send.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![crate_name = "foo"]

// @has 'foo/struct.Foo.html'
// @has - '//*[@id="impl-Send"]' 'impl !Send for Foo'
// @has - '//*[@id="impl-Sync"]' 'impl !Sync for Foo'
pub struct Foo(*const i8);
pub trait Whatever: Send {}
impl<T: Send + ?Sized> Whatever for T {}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async fn return_targets_async_block_not_async_fn() -> u8 {
return 0u8;
};
let _: &dyn Future<Output = ()> = &block;
//~^ ERROR type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
//~^ ERROR type mismatch resolving `<impl Future as Future>::Output == ()`
}

fn no_break_in_async_block() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ LL | |
LL | | }
| |_^ expected `u8`, found `()`

error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
error[E0271]: type mismatch resolving `<impl Future as Future>::Output == ()`
--> $DIR/async-block-control-flow-static-semantics.rs:26:39
|
LL | let _: &dyn Future<Output = ()> = &block;
Expand All @@ -47,7 +47,7 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
| |
| implicitly returns `()` as its body has no tail or `return` expression

error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
error[E0271]: type mismatch resolving `<impl Future as Future>::Output == ()`
--> $DIR/async-block-control-flow-static-semantics.rs:17:39
|
LL | let _: &dyn Future<Output = ()> = &block;
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/async-await/generator-desc.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
| the expected opaque type
| the found opaque type
|
= note: expected opaque type `impl Future<Output = [async output]>` (`async` closure body)
found opaque type `impl Future<Output = [async output]>` (`async` closure body)
= note: expected opaque type `impl Future` (`async` closure body)
found opaque type `impl Future` (`async` closure body)

error: aborting due to 3 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/issue-67252-unnamed-future.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
LL | spawn(async {
| ^^^^^ future created by async block is not `Send`
|
= help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `*mut ()`
= help: within `impl Future`, the trait `Send` is not implemented for `*mut ()`
note: future is not `Send` as this value is used across an await
--> $DIR/issue-67252-unnamed-future.rs:20:16
|
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/async-await/issue-68112.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ LL | require_send(send_fut);
= note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
= note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>`
= note: required because it appears within the type `impl Future<Output = [async output]>`
= note: required because it appears within the type `impl Future`
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
= note: required because it appears within the type `{ResumeTy, impl Future<Output = Arc<RefCell<i32>>>, (), i32, Ready<i32>}`
= note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>`
= note: required because it appears within the type `impl Future<Output = [async output]>`
= note: required because it appears within the type `impl Future`
note: required by a bound in `require_send`
--> $DIR/issue-68112.rs:11:25
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
LL | assert_send(async {
| ^^^^^^^^^^^ future created by async block is not `Send`
|
= help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `*const u8`
= help: within `impl Future`, the trait `Send` is not implemented for `*const u8`
note: future is not `Send` as this value is used across an await
--> $DIR/issue-65436-raw-ptr-not-send.rs:14:35
|
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/partial-drop-partial-reinit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ LL | async fn foo() {
= note: required because it appears within the type `{ResumeTy, (NotSend,), impl Future<Output = ()>, ()}`
= note: required because it appears within the type `[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]>`
= note: required because it appears within the type `impl Future<Output = [async output]>`
= note: required because it appears within the type `impl Future`
= note: required because it appears within the type `impl Future<Output = ()>`
note: required by a bound in `gimme_send`
--> $DIR/partial-drop-partial-reinit.rs:10:18
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/chalkify/bugs/async.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ note: required by a bound in `from_generator`
LL | T: Generator<ResumeTy, Yield = ()>,
| ^^^^^^^^^^ required by this bound in `from_generator`

error[E0280]: the requirement `<impl Future<Output = [async output]> as Future>::Output == u32` is not satisfied
error[E0280]: the requirement `<impl Future as Future>::Output == u32` is not satisfied
--> $DIR/async.rs:7:25
|
LL | async fn foo(x: u32) -> u32 {
Expand Down
40 changes: 40 additions & 0 deletions src/test/ui/coherence/deep-bad-copy-reason.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#![feature(extern_types)]

extern "Rust" {
type OpaqueListContents;
}

pub struct ListS<T> {
len: usize,
data: [T; 0],
opaque: OpaqueListContents,
}

pub struct Interned<'a, T>(&'a T);

impl<'a, T> Clone for Interned<'a, T> {
fn clone(&self) -> Self {
*self
}
}

impl<'a, T> Copy for Interned<'a, T> {}

pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
//~^ NOTE this field does not implement `Copy`
//~| NOTE the `Copy` impl for `Interned<'tcx, ListS<T>>` requires that `OpaqueListContents: Sized`

impl<'tcx, T> Clone for List<'tcx, T> {
fn clone(&self) -> Self {
*self
}
}

impl<'tcx, T> Copy for List<'tcx, T> {}
//~^ ERROR the trait `Copy` may not be implemented for this type

fn assert_is_copy<T: Copy>() {}

fn main() {
assert_is_copy::<List<'static, ()>>();
}
18 changes: 18 additions & 0 deletions src/test/ui/coherence/deep-bad-copy-reason.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/deep-bad-copy-reason.rs:33:15
|
LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
| ------------------------ this field does not implement `Copy`
...
LL | impl<'tcx, T> Copy for List<'tcx, T> {}
| ^^^^
|
note: the `Copy` impl for `Interned<'tcx, ListS<T>>` requires that `OpaqueListContents: Sized`
--> $DIR/deep-bad-copy-reason.rs:23:26
|
LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0204`.
2 changes: 1 addition & 1 deletion src/test/ui/consts/const-deref-ptr.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer
--> $DIR/const-deref-ptr.rs:4:29
|
LL | static C: u64 = unsafe {*(0xdeadbeef as *const u64)};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0xdeadbeef is not a valid pointer
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0xdeadbeef is not a valid pointer

error: aborting due to previous error

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ error[E0080]: evaluation of constant value failed
--> $DIR/const_raw_ptr_ops2.rs:7:26
|
LL | const Z2: i32 = unsafe { *(42 as *const i32) };
| ^^^^^^^^^^^^^^^^^^^ 0x2a is not a valid pointer
| ^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2a is not a valid pointer

error[E0080]: evaluation of constant value failed
--> $DIR/const_raw_ptr_ops2.rs:9:26
|
LL | const Z3: i32 = unsafe { *(44 as *const i32) };
| ^^^^^^^^^^^^^^^^^^^ 0x2c is not a valid pointer
| ^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2c is not a valid pointer

error: aborting due to 2 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ error[E0080]: could not evaluate static initializer
--> $DIR/ub-wide-ptr.rs:135:5
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ null pointer is not a valid pointer for this operation
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer

error[E0080]: could not evaluate static initializer
--> $DIR/ub-wide-ptr.rs:139:5
Expand Down
Loading

0 comments on commit 37b55c8

Please sign in to comment.