Skip to content
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

Stabilize RFC3324 dyn upcasting coercion #118133

Merged
merged 1 commit into from
Nov 22, 2023
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
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ declare_features! (
/// Allows `#[track_caller]` to be used which provides
/// accurate caller location reporting during panic (RFC 2091).
(accepted, track_caller, "1.46.0", Some(47809), None),
/// Allows dyn upcasting trait objects via supertraits.
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
(accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991), None),
/// Allows #[repr(transparent)] on univariant enums (RFC 2645).
(accepted, transparent_enums, "1.42.0", Some(60405), None),
/// Allows indexing tuples.
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,9 +562,6 @@ declare_features! (
(unstable, thread_local, "1.0.0", Some(29594), None),
/// Allows defining `trait X = A + B;` alias items.
(unstable, trait_alias, "1.24.0", Some(41517), None),
/// Allows dyn upcasting trait objects via supertraits.
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
(unstable, trait_upcasting, "1.56.0", Some(65991), None),
/// Allows for transmuting between arrays with sizes that contain generic consts.
(unstable, transmute_generic_consts, "1.70.0", Some(109929), None),
/// Allows #[repr(transparent)] on unions (RFC 2645).
Expand Down
23 changes: 0 additions & 23 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
)];

let mut has_unsized_tuple_coercion = false;
let mut has_trait_upcasting_coercion = None;

// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
Expand Down Expand Up @@ -694,13 +693,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// these here and emit a feature error if coercion doesn't fail
// due to another reason.
match impl_source {
traits::ImplSource::Builtin(
BuiltinImplSource::TraitUpcasting { .. },
_,
) => {
has_trait_upcasting_coercion =
Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
}
traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
has_unsized_tuple_coercion = true;
}
Expand All @@ -711,21 +703,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
}

if let Some((sub, sup)) = has_trait_upcasting_coercion
&& !self.tcx().features().trait_upcasting
{
// Renders better when we erase regions, since they're not really the point here.
let (sub, sup) = self.tcx.erase_regions((sub, sup));
let mut err = feature_err(
&self.tcx.sess.parse_sess,
sym::trait_upcasting,
self.cause.span,
format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"),
);
err.note(format!("required when coercing `{source}` into `{target}`"));
err.emit();
}

if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
feature_err(
&self.tcx.sess.parse_sess,
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,9 @@ lint_requested_level = requested on the command line with `{$level} {$lint_name}

lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`

lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
.label = target type is set here
lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion
.help = consider removing this implementation or replacing it with a method instead
.label = target type is a supertrait of `{$t}`

lint_suspicious_double_ref_clone =
using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type
Expand Down
15 changes: 3 additions & 12 deletions compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@ use crate::{

use rustc_hir as hir;
use rustc_middle::ty;
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_span::sym;
use rustc_trait_selection::traits::supertraits;

declare_lint! {
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
///
/// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
/// The `deref` functions will no longer be called implicitly, so there might be behavior change.
///
/// ### Example
///
/// ```rust,compile_fail
Expand Down Expand Up @@ -44,15 +40,10 @@ declare_lint! {
///
/// ### Explanation
///
/// The dyn upcasting coercion feature adds new coercion rules, taking priority
/// over certain other coercion rules, which will cause some behavior change.
/// The implicit dyn upcasting coercion take priority over those `Deref` impls.
pub DEREF_INTO_DYN_SUPERTRAIT,
Warn,
"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
};
"`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion",
}

declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);
Expand Down Expand Up @@ -90,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
cx.emit_spanned_lint(
DEREF_INTO_DYN_SUPERTRAIT,
tcx.def_span(item.owner_id.def_id),
SupertraitAsDerefTarget { t, target_principal, label },
SupertraitAsDerefTarget { t, label },
);
}
}
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ use rustc_errors::{
};
use rustc_hir::def_id::DefId;
use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{
inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
};
use rustc_middle::ty::{inhabitedness::InhabitedPredicate, Clause, Ty, TyCtxt};
use rustc_session::parse::ParseSess;
use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};

Expand Down Expand Up @@ -556,9 +554,9 @@ pub enum BuiltinSpecialModuleNameUsed {
// deref_into_dyn_supertrait.rs
#[derive(LintDiagnostic)]
#[diag(lint_supertrait_as_deref_target)]
#[help]
pub struct SupertraitAsDerefTarget<'a> {
pub t: Ty<'a>,
pub target_principal: PolyExistentialTraitRef<'a>,
#[subdiagnostic]
pub label: Option<SupertraitAsDerefTargetLabel>,
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
#![feature(control_flow_enum)]
#![feature(trait_upcasting)]
#![cfg_attr(bootstrap, feature(trait_upcasting))]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(try_reserve_kind)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@
use hir::def_id::DefId;
use hir::LangItem;
use rustc_hir as hir;
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, Ty, TypeVisitableExt};

use crate::traits;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::util;

use super::BuiltinImplConditions;
Expand Down Expand Up @@ -690,45 +687,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
})
}

/// Temporary migration for #89190
fn need_migrate_deref_output_trait_object(
&mut self,
ty: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
cause: &ObligationCause<'tcx>,
) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
let tcx = self.tcx();
if tcx.features().trait_upcasting {
return None;
}

// <ty as Deref>
let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);

let obligation =
traits::Obligation::new(tcx, cause.clone(), param_env, ty::Binder::dummy(trait_ref));
if !self.infcx.predicate_may_hold(&obligation) {
return None;
}

self.infcx.probe(|_| {
let ty = traits::normalize_projection_type(
self,
param_env,
ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args),
cause.clone(),
0,
// We're *intentionally* throwing these away,
// since we don't actually use them.
&mut vec![],
)
.ty()
.unwrap();

if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None }
})
}

/// Searches for unsizing that might apply to `obligation`.
fn assemble_candidates_for_unsizing(
&mut self,
Expand Down Expand Up @@ -786,15 +744,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let principal_a = a_data.principal().unwrap();
let target_trait_did = principal_def_id_b.unwrap();
let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object(
source,
obligation.param_env,
&obligation.cause,
) {
if deref_trait_ref.def_id() == target_trait_did {
return;
}
}

for (idx, upcast_trait_ref) in
util::supertraits(self.tcx(), source_trait_ref).enumerate()
Expand Down
2 changes: 1 addition & 1 deletion library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
#![feature(slice_flatten)]
#![feature(error_generic_member_access)]
#![feature(error_in_core)]
#![feature(trait_upcasting)]
#![cfg_attr(bootstrap, feature(trait_upcasting))]
#![feature(utf8_chunks)]
#![feature(is_ascii_octdigit)]
#![feature(get_many_mut)]
Expand Down
27 changes: 0 additions & 27 deletions src/doc/unstable-book/src/language-features/trait-upcasting.md

This file was deleted.

2 changes: 1 addition & 1 deletion src/tools/miri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#![feature(round_ties_even)]
#![feature(let_chains)]
#![feature(lint_reasons)]
#![feature(trait_upcasting)]
#![cfg_attr(bootstrap, feature(trait_upcasting))]
// Configure clippy and other lints
#![allow(
clippy::collapsible_else_if,
Expand Down
3 changes: 0 additions & 3 deletions src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#![feature(trait_upcasting)]
#![allow(incomplete_features)]

trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
fn a(&self) -> i32 {
10
Expand Down
3 changes: 1 addition & 2 deletions src/tools/miri/tests/pass/box-custom-alloc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//@revisions: stack tree
//@[tree]compile-flags: -Zmiri-tree-borrows
#![allow(incomplete_features)] // for trait upcasting
#![feature(allocator_api, trait_upcasting)]
#![feature(allocator_api)]

use std::alloc::Layout;
use std::alloc::{AllocError, Allocator};
Expand Down
3 changes: 0 additions & 3 deletions src/tools/miri/tests/pass/dyn-upcast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#![feature(trait_upcasting)]
#![allow(incomplete_features)]

fn main() {
basic();
diamond();
Expand Down
1 change: 0 additions & 1 deletion tests/ui/codegen/issue-99551.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// build-pass
#![feature(trait_upcasting)]

pub trait A {}
pub trait B {}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(dyn_star, trait_upcasting)]
#![feature(dyn_star)]
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes

trait A: B {}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/no-unsize-coerce-dyn-trait.rs:1:12
|
LL | #![feature(dyn_star, trait_upcasting)]
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/dyn-star/upcast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// known-bug: #104800

#![feature(dyn_star, trait_upcasting)]
#![feature(dyn_star)]

trait Foo: Bar {
fn hello(&self);
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/dyn-star/upcast.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/upcast.rs:3:12
|
LL | #![feature(dyn_star, trait_upcasting)]
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
Expand Down
13 changes: 0 additions & 13 deletions tests/ui/feature-gates/feature-gate-trait_upcasting.rs

This file was deleted.

13 changes: 0 additions & 13 deletions tests/ui/feature-gates/feature-gate-trait_upcasting.stderr

This file was deleted.

2 changes: 0 additions & 2 deletions tests/ui/traits/new-solver/normalize-unsize-rhs.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// compile-flags: -Ztrait-solver=next
// check-pass

#![feature(trait_upcasting)]

trait A {}
trait B: A {}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// check-pass
// compile-flags: -Ztrait-solver=next

#![feature(trait_upcasting)]

pub trait A {}
pub trait B: A {}

Expand Down
2 changes: 0 additions & 2 deletions tests/ui/traits/new-solver/upcast-right-substs.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// compile-flags: -Ztrait-solver=next
// check-pass

#![feature(trait_upcasting)]

trait Foo: Bar<i32> + Bar<u32> {}

trait Bar<T> {}
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/traits/new-solver/upcast-wrong-substs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// compile-flags: -Ztrait-solver=next

#![feature(trait_upcasting)]

trait Foo: Bar<i32> + Bar<u32> {}

trait Bar<T> {}
Expand Down
Loading
Loading