diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 24c1fe43d0c68..ca1106384fd33 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -700,8 +700,13 @@ where assert_eq!(src.layout.size, dest.layout.size); } + // Setting `nonoverlapping` here only has an effect when we don't hit the fast-path above, + // but that should at least match what LLVM does where `memcpy` is also only used when the + // type does not have Scalar/ScalarPair layout. + // (Or as the `Assign` docs put it, assignments "not producing primitives" must be + // non-overlapping.) self.mem_copy( - src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ false, + src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ true, ) } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 270b90fa6b210..120545c8e5dc5 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -722,7 +722,14 @@ pub(super) fn check_specialization_validity<'tcx>( let result = opt_result.unwrap_or(Ok(())); if let Err(parent_impl) = result { - report_forbidden_specialization(tcx, impl_item, parent_impl); + if !tcx.is_impl_trait_in_trait(impl_item) { + report_forbidden_specialization(tcx, impl_item, parent_impl); + } else { + tcx.sess.delay_span_bug( + DUMMY_SP, + format!("parent item: {:?} not marked as default", parent_impl), + ); + } } } @@ -1485,7 +1492,9 @@ fn opaque_type_cycle_error( } for closure_def_id in visitor.closures { - let Some(closure_local_did) = closure_def_id.as_local() else { continue; }; + let Some(closure_local_did) = closure_def_id.as_local() else { + continue; + }; let typeck_results = tcx.typeck(closure_local_did); let mut label_match = |ty: Ty<'_>, span| { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 97a3e01c52a31..acd0bcd8e5c91 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_session::lint; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Ident}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::fmt; use crate::errors; @@ -338,7 +338,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { Scope::TraitRefBoundary { .. } => { // We should only see super trait lifetimes if there is a `Binder` above - assert!(supertrait_bound_vars.is_empty()); + // though this may happen when we call `poly_trait_ref_binder_info` with + // an (erroneous, #113423) associated return type bound in an impl header. + if !supertrait_bound_vars.is_empty() { + self.tcx.sess.delay_span_bug( + DUMMY_SP, + format!( + "found supertrait lifetimes without a binder to append \ + them to: {supertrait_bound_vars:?}" + ), + ); + } break (vec![], BinderScopeType::Normal); } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 49aee6b59a28c..066e7449189ea 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -7,7 +7,7 @@ use rustc_arena::DroplessArena; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, CrateVariancesMap, ImplTraitInTraitData, SubstsRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable}; use std::ops::ControlFlow; @@ -59,13 +59,6 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => { return variance_of_opaque(tcx, item_def_id); } - DefKind::AssocTy => { - if let Some(ImplTraitInTraitData::Trait { .. }) = - tcx.opt_rpitit_info(item_def_id.to_def_id()) - { - return variance_of_opaque(tcx, item_def_id); - } - } _ => {} } @@ -125,7 +118,8 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary // at all for RPITITs. ty::Alias(_, ty::AliasTy { def_id, substs, .. }) - if self.tcx.is_impl_trait_in_trait(*def_id) => + if self.tcx.is_impl_trait_in_trait(*def_id) + && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() => { self.visit_opaque(*def_id, substs) } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 3098b8bc2f9b2..5927f79a18333 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -473,17 +473,6 @@ where } } - ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => { - // Skip lifetime parameters that are not captures. - let variances = self.tcx.variances_of(proj.def_id); - - for (v, s) in std::iter::zip(variances, proj.substs.iter()) { - if *v != ty::Variance::Bivariant { - s.visit_with(self); - } - } - } - _ => { ty.super_visit_with(self); } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0fe801ad2ed1a..d95b05ef75408 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1110,12 +1110,11 @@ where /// /// This takes two primary parameters: /// -/// * `codegen_fn_attr_flags` - these are flags calculated as part of the -/// codegen attrs for a defined function. For function pointers this set of -/// flags is the empty set. This is only applicable for Rust-defined -/// functions, and generally isn't needed except for small optimizations where -/// we try to say a function which otherwise might look like it could unwind -/// doesn't actually unwind (such as for intrinsics and such). +/// * `fn_def_id` - the `DefId` of the function. If this is provided then we can +/// determine more precisely if the function can unwind. If this is not provided +/// then we will only infer whether the function can unwind or not based on the +/// ABI of the function. For example, a function marked with `#[rustc_nounwind]` +/// is known to not unwind even if it's using Rust ABI. /// /// * `abi` - this is the ABI that the function is defined with. This is the /// primary factor for determining whether a function can unwind or not. @@ -1147,11 +1146,6 @@ where /// aborts the process. /// * This affects whether functions have the LLVM `nounwind` attribute, which /// affects various optimizations and codegen. -/// -/// FIXME: this is actually buggy with respect to Rust functions. Rust functions -/// compiled with `-Cpanic=unwind` and referenced from another crate compiled -/// with `-Cpanic=abort` will look like they can't unwind when in fact they -/// might (from a foreign exception or similar). #[inline] #[tracing::instrument(level = "debug", skip(tcx))] pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option, abi: SpecAbi) -> bool { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 66a627d5aac7c..5c6d43e50ea28 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -759,7 +759,6 @@ symbols! { from_desugaring, from_fn, from_iter, - from_method, from_output, from_residual, from_size_align_unchecked, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 1e4d30f48b2dc..b16d2eb5fc19e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -41,7 +41,6 @@ pub trait TypeErrCtxtExt<'tcx> { static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ kw::SelfUpper, sym::ItemContext, - sym::from_method, sym::from_desugaring, sym::direct, sym::cause, @@ -172,23 +171,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - if let ObligationCauseCode::ItemObligation(item) - | ObligationCauseCode::BindingObligation(item, _) - | ObligationCauseCode::ExprItemObligation(item, ..) - | ObligationCauseCode::ExprBindingObligation(item, ..) = *obligation.cause.code() - { - // FIXME: maybe also have some way of handling methods - // from other traits? That would require name resolution, - // which we might want to be some sort of hygienic. - // - // Currently I'm leaving it for what I need for `try`. - if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { - let method = self.tcx.item_name(item); - flags.push((sym::from_method, None)); - flags.push((sym::from_method, Some(method.to_string()))); - } - } - if let Some(k) = obligation.cause.span.desugaring_kind() { flags.push((sym::from_desugaring, None)); flags.push((sym::from_desugaring, Some(format!("{:?}", k)))); @@ -672,7 +654,7 @@ impl<'tcx> OnUnimplementedFormatString { None => { if let Some(val) = options.get(&s) { val - } else if s == sym::from_desugaring || s == sym::from_method { + } else if s == sym::from_desugaring { // don't break messages using these two arguments incorrectly &empty_string } else if s == sym::ItemContext { diff --git a/src/tools/cargo b/src/tools/cargo index 5b377cece0e0d..45782b6b8afd1 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 5b377cece0e0dd0af686cf53ce4637d5d85c2a10 +Subproject commit 45782b6b8afd1da042d45c2daeec9c0744f72cc7 diff --git a/src/tools/miri/tests/fail/overlapping_assignment.rs b/src/tools/miri/tests/fail/overlapping_assignment.rs new file mode 100644 index 0000000000000..84994c179f9ea --- /dev/null +++ b/src/tools/miri/tests/fail/overlapping_assignment.rs @@ -0,0 +1,23 @@ +#![feature(core_intrinsics)] +#![feature(custom_mir)] + +use std::intrinsics::mir::*; + +// It's not that easy to fool the MIR validity check +// which wants to prevent overlapping assignments... +// So we use two separate pointer arguments, and then arrange for them to alias. +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn self_copy(ptr1: *mut [i32; 4], ptr2: *mut [i32; 4]) { + mir! { + { + *ptr1 = *ptr2; //~ERROR: overlapping ranges + Return() + } + } +} + +pub fn main() { + let mut x = [0; 4]; + let ptr = std::ptr::addr_of_mut!(x); + self_copy(ptr, ptr); +} diff --git a/src/tools/miri/tests/fail/overlapping_assignment.stderr b/src/tools/miri/tests/fail/overlapping_assignment.stderr new file mode 100644 index 0000000000000..42a000dfcc6c7 --- /dev/null +++ b/src/tools/miri/tests/fail/overlapping_assignment.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges + --> $DIR/overlapping_assignment.rs:LL:CC + | +LL | *ptr1 = *ptr2; + | ^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `self_copy` at $DIR/overlapping_assignment.rs:LL:CC +note: inside `main` + --> $DIR/overlapping_assignment.rs:LL:CC + | +LL | self_copy(ptr, ptr); + | ^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.current.stderr b/tests/ui/async-await/in-trait/missing-feature-flag.current.stderr new file mode 100644 index 0000000000000..e6ac9bc2277ba --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-feature-flag.current.stderr @@ -0,0 +1,30 @@ +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/missing-feature-flag.rs:14:1 + | +LL | async fn foo(_: T) -> &'static str; + | ----------------------------------- `foo` from trait +... +LL | impl MyTrait for MyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/missing-feature-flag.rs:18:5 + | +LL | impl MyTrait for MyStruct {} + | ------------------------------- parent `impl` is here +... +LL | async fn foo(_: i32) -> &'static str {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0308]: mismatched types + --> $DIR/missing-feature-flag.rs:18:42 + | +LL | async fn foo(_: i32) -> &'static str {} + | ^^ expected `&str`, found `()` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0046, E0308, E0520. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.next.stderr b/tests/ui/async-await/in-trait/missing-feature-flag.next.stderr new file mode 100644 index 0000000000000..e6ac9bc2277ba --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-feature-flag.next.stderr @@ -0,0 +1,30 @@ +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/missing-feature-flag.rs:14:1 + | +LL | async fn foo(_: T) -> &'static str; + | ----------------------------------- `foo` from trait +... +LL | impl MyTrait for MyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/missing-feature-flag.rs:18:5 + | +LL | impl MyTrait for MyStruct {} + | ------------------------------- parent `impl` is here +... +LL | async fn foo(_: i32) -> &'static str {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0308]: mismatched types + --> $DIR/missing-feature-flag.rs:18:42 + | +LL | async fn foo(_: i32) -> &'static str {} + | ^^ expected `&str`, found `()` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0046, E0308, E0520. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.rs b/tests/ui/async-await/in-trait/missing-feature-flag.rs new file mode 100644 index 0000000000000..6481f4a70595f --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-feature-flag.rs @@ -0,0 +1,23 @@ +// edition:2018 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next + +#![feature(async_fn_in_trait)] +#![feature(min_specialization)] + +struct MyStruct; + +trait MyTrait { + async fn foo(_: T) -> &'static str; +} + +impl MyTrait for MyStruct {} +//~^ ERROR: not all trait items implemented, missing: `foo` [E0046] + +impl MyTrait for MyStruct { + async fn foo(_: i32) -> &'static str {} + //~^ ERROR: `foo` specializes an item from a parent `impl`, but that item is not marked `default` [E0520] + //~| ERROR: mismatched types [E0308] +} + +fn main() {} diff --git a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs new file mode 100644 index 0000000000000..1b16a492a7a1a --- /dev/null +++ b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs @@ -0,0 +1,13 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +// Shouldn't ICE when we have a (bad) RTN in an impl header + +trait Super1<'a> { + fn bar<'b>() -> bool; +} + +impl Super1<'_, bar(): Send> for () {} +//~^ ERROR associated type bindings are not allowed here + +fn main() {} diff --git a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr new file mode 100644 index 0000000000000..52d8168c9d836 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr @@ -0,0 +1,18 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/rtn-in-impl-signature.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0229]: associated type bindings are not allowed here + --> $DIR/rtn-in-impl-signature.rs:10:17 + | +LL | impl Super1<'_, bar(): Send> for () {} + | ^^^^^^^^^^^ associated type not allowed here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.current.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.current.stderr new file mode 100644 index 0000000000000..ff30103b771dd --- /dev/null +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.current.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `impl Foo: Foo` is not satisfied + --> $DIR/return-dont-satisfy-bounds.rs:13:34 + | +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `impl Foo` + | + = help: the trait `Foo` is implemented for `Bar` +note: required by a bound in `Foo::foo::{opaque#0}` + --> $DIR/return-dont-satisfy-bounds.rs:7:30 + | +LL | fn foo(self) -> impl Foo; + | ^^^^^^ required by this bound in `Foo::foo::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.next.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.next.stderr new file mode 100644 index 0000000000000..7c7f7feaa5506 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.next.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `impl Foo: Foo` is not satisfied + --> $DIR/return-dont-satisfy-bounds.rs:13:34 + | +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `impl Foo` + | + = help: the trait `Foo` is implemented for `Bar` +note: required by a bound in `Foo::{opaque#0}` + --> $DIR/return-dont-satisfy-bounds.rs:7:30 + | +LL | fn foo(self) -> impl Foo; + | ^^^^^^ required by this bound in `Foo::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs new file mode 100644 index 0000000000000..65528f212e296 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs @@ -0,0 +1,19 @@ +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next + +#![feature(return_position_impl_trait_in_trait)] + +trait Foo { + fn foo(self) -> impl Foo; +} + +struct Bar; + +impl Foo for Bar { + fn foo>(self) -> impl Foo { + //~^ ERROR: the trait bound `impl Foo: Foo` is not satisfied [E0277] + self + } +} + +fn main() {} diff --git a/triagebot.toml b/triagebot.toml index 4bab8facc85b0..e6c593204cad0 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -20,6 +20,7 @@ allow-unauthenticated = [ "regression-*", "perf-*", "AsyncAwait-OnDeck", + "needs-triage", ] [glacier] @@ -254,6 +255,9 @@ trigger_files = [ [autolabel."S-waiting-on-review"] new_pr = true +[autolabel."needs-triage"] +new_issue = true + [autolabel."WG-trait-system-refactor"] trigger_files = [ "compiler/rustc_trait_selection/src/solve",