Auto merge of #120251 - matthiaskrgr:rollup-gttrw68, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #119664 (Fix tty detection for msys2's `/dev/ptmx`)
 - #120104 (never_patterns: Count `!` bindings as diverging)
 - #120109 (Move cmath into `sys`)
 - #120143 (Consolidate logic around resolving built-in coroutine trait impls)
 - #120159 (Track `verbose` and `verbose_internals`)
 - #120216 (Fix a `trimmed_def_paths` assertion failure.)
 - #120220 (Document `Token{Stream,Tree}::Display` more thoroughly.)
 - #120233 (Revert stabilization of trait_upcasting feature)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-01-22 22:04:50 +00:00
commit d6b151fc77
109 changed files with 826 additions and 224 deletions

View File

@ -339,9 +339,6 @@ 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)),
/// Allows dyn upcasting trait objects via supertraits.
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
(accepted, trait_upcasting, "1.76.0", Some(65991)),
/// Allows #[repr(transparent)] on univariant enums (RFC 2645).
(accepted, transparent_enums, "1.42.0", Some(60405)),
/// Allows indexing tuples.

View File

@ -584,6 +584,9 @@ declare_features! (
(unstable, thread_local, "1.0.0", Some(29594)),
/// Allows defining `trait X = A + B;` alias items.
(unstable, trait_alias, "1.24.0", Some(41517)),
/// 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)),
/// Allows for transmuting between arrays with sizes that contain generic consts.
(unstable, transmute_generic_consts, "1.70.0", Some(109929)),
/// Allows #[repr(transparent)] on unions (RFC 2645).

View File

@ -213,8 +213,11 @@ language_item_table! {
Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0);
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1);
CoroutineResume, sym::coroutine_resume, coroutine_resume, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;

View File

@ -2,8 +2,7 @@ use std::cell::RefCell;
use crate::coercion::CoerceMany;
use crate::gather_locals::GatherLocalsVisitor;
use crate::CoroutineTypes;
use crate::FnCtxt;
use crate::{CoroutineTypes, Diverges, FnCtxt};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::intravisit::Visitor;
@ -76,6 +75,12 @@ pub(super) fn check_fn<'a, 'tcx>(
let ty: Option<&hir::Ty<'_>> = try { inputs_hir?.get(idx)? };
let ty_span = ty.map(|ty| ty.span);
fcx.check_pat_top(param.pat, param_ty, ty_span, None, None);
if param.pat.is_never_pattern() {
fcx.function_diverges_because_of_empty_arguments.set(Diverges::Always {
span: param.pat.span,
custom_note: Some("any code following a never pattern is unreachable"),
});
}
// Check that argument is Sized.
if !params_can_be_unsized {
@ -105,6 +110,7 @@ pub(super) fn check_fn<'a, 'tcx>(
hir::FnRetTy::Return(ty) => ty.span,
};
fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
fcx.is_whole_body.set(true);
fcx.check_return_expr(body.value, false);
// Finalize the return check by taking the LUB of the return types

View File

@ -625,6 +625,7 @@ 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
@ -692,6 +693,13 @@ 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;
}
@ -702,6 +710,21 @@ 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,
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,

View File

@ -208,10 +208,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// without the final expr (e.g. `try { return; }`). We don't want to generate an
// unreachable_code lint for it since warnings for autogenerated code are confusing.
let is_try_block_generated_unit_expr = match expr.kind {
ExprKind::Call(_, args) if expr.span.is_desugaring(DesugaringKind::TryBlock) => {
args.len() == 1 && args[0].span.is_desugaring(DesugaringKind::TryBlock)
ExprKind::Call(_, [arg]) => {
expr.span.is_desugaring(DesugaringKind::TryBlock)
&& arg.span.is_desugaring(DesugaringKind::TryBlock)
}
_ => false,
};
@ -220,9 +220,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.warn_if_unreachable(expr.hir_id, expr.span, "expression");
}
// Hide the outer diverging and has_errors flags.
// Whether a past expression diverges doesn't affect typechecking of this expression, so we
// reset `diverges` while checking `expr`.
let old_diverges = self.diverges.replace(Diverges::Maybe);
if self.is_whole_body.replace(false) {
// If this expression is the whole body and the function diverges because of its
// arguments, we check this here to ensure the body is considered to diverge.
self.diverges.set(self.function_diverges_because_of_empty_arguments.get())
};
let ty = ensure_sufficient_stack(|| match &expr.kind {
hir::ExprKind::Path(
qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)),

View File

@ -1471,6 +1471,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Type check a `let` statement.
pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
self.check_decl(local.into());
if local.pat.is_never_pattern() {
self.diverges.set(Diverges::Always {
span: local.pat.span,
custom_note: Some("any code following a never pattern is unreachable"),
});
}
}
pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {

View File

@ -103,6 +103,13 @@ pub struct FnCtxt<'a, 'tcx> {
/// the diverges flag is set to something other than `Maybe`.
pub(super) diverges: Cell<Diverges>,
/// If one of the function arguments is a never pattern, this counts as diverging code. This
/// affect typechecking of the function body.
pub(super) function_diverges_because_of_empty_arguments: Cell<Diverges>,
/// Whether the currently checked node is the whole body of the function.
pub(super) is_whole_body: Cell<bool>,
pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,
pub(super) inh: &'a Inherited<'tcx>,
@ -124,6 +131,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ret_coercion_span: Cell::new(None),
coroutine_types: None,
diverges: Cell::new(Diverges::Maybe),
function_diverges_because_of_empty_arguments: Cell::new(Diverges::Maybe),
is_whole_body: Cell::new(false),
enclosing_breakables: RefCell::new(EnclosingBreakables {
stack: Vec::new(),
by_id: Default::default(),

View File

@ -98,6 +98,7 @@ fn assert_same_hash(x: &Options, y: &Options) {
assert_same_clone(y);
}
#[track_caller]
fn assert_different_hash(x: &Options, y: &Options) {
assert_ne!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
@ -713,7 +714,6 @@ fn test_unstable_options_tracking_hash() {
untracked!(unpretty, Some("expanded".to_string()));
untracked!(unstable_options, true);
untracked!(validate_mir, true);
untracked!(verbose_internals, true);
untracked!(write_long_types_to_disk, false);
// tidy-alphabetical-end
@ -845,6 +845,7 @@ fn test_unstable_options_tracking_hash() {
};
}
tracked_no_crate_hash!(no_codegen, true);
tracked_no_crate_hash!(verbose_internals, true);
}
#[test]

View File

@ -5,6 +5,7 @@ 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;
@ -12,6 +13,9 @@ 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
@ -40,10 +44,15 @@ declare_lint! {
///
/// ### Explanation
///
/// The implicit dyn upcasting coercion take priority over those `Deref` impls.
/// The dyn upcasting coercion feature adds new coercion rules, taking priority
/// over certain other coercion rules, which will cause some behavior change.
pub DEREF_INTO_DYN_SUPERTRAIT,
Warn,
"`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion",
"`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>",
};
}
declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);

View File

@ -35,6 +35,7 @@
#![feature(iter_intersperse)]
#![feature(iter_order_by)]
#![feature(let_chains)]
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(rustc_attrs)]

View File

@ -532,7 +532,6 @@ pub enum BuiltinSpecialModuleNameUsed {
// deref_into_dyn_supertrait.rs
#[derive(LintDiagnostic)]
#[diag(lint_supertrait_as_deref_target)]
#[help]
pub struct SupertraitAsDerefTarget<'a> {
pub self_ty: Ty<'a>,
pub supertrait_principal: PolyExistentialTraitRef<'a>,

View File

@ -49,6 +49,7 @@
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
#![feature(control_flow_enum)]
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(try_reserve_kind)]

View File

@ -3,6 +3,7 @@ use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
use crate::ty::{EarlyBinder, GenericArgs, GenericArgsRef, TypeVisitableExt};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::lang_items::LangItem;
@ -11,6 +12,7 @@ use rustc_macros::HashStable;
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
use rustc_span::Symbol;
use std::assert_matches::assert_matches;
use std::fmt;
/// A monomorphized `InstanceDef`.
@ -572,6 +574,54 @@ impl<'tcx> Instance<'tcx> {
Some(Instance { def, args })
}
pub fn try_resolve_item_for_coroutine(
tcx: TyCtxt<'tcx>,
trait_item_id: DefId,
trait_id: DefId,
rcvr_args: ty::GenericArgsRef<'tcx>,
) -> Option<Instance<'tcx>> {
let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
return None;
};
let coroutine_kind = tcx.coroutine_kind(coroutine_def_id).unwrap();
let lang_items = tcx.lang_items();
let coroutine_callable_item = if Some(trait_id) == lang_items.future_trait() {
assert_matches!(
coroutine_kind,
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
);
hir::LangItem::FuturePoll
} else if Some(trait_id) == lang_items.iterator_trait() {
assert_matches!(
coroutine_kind,
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
);
hir::LangItem::IteratorNext
} else if Some(trait_id) == lang_items.async_iterator_trait() {
assert_matches!(
coroutine_kind,
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
);
hir::LangItem::AsyncIteratorPollNext
} else if Some(trait_id) == lang_items.coroutine_trait() {
assert_matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
hir::LangItem::CoroutineResume
} else {
return None;
};
if tcx.lang_items().get(coroutine_callable_item) == Some(trait_item_id) {
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args })
} else {
// All other methods should be defaulted methods of the built-in trait.
// This is important for `Iterator`'s combinators, but also useful for
// adding future default methods to `Future`, for instance.
debug_assert!(tcx.defaultness(trait_item_id).has_value());
Some(Instance::new(trait_item_id, rcvr_args))
}
}
/// Depending on the kind of `InstanceDef`, the MIR body associated with an
/// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
/// cases the MIR body is expressed in terms of the types found in the substitution array.

View File

@ -3072,8 +3072,6 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
// this is pub to be able to intra-doc-link it
pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
assert!(tcx.sess.opts.trimmed_def_paths);
// Trimming paths is expensive and not optimized, since we expect it to only be used for error
// reporting.
//

View File

@ -224,7 +224,7 @@ top_level_options!(
working_dir: RealFileName [TRACKED],
color: ColorConfig [UNTRACKED],
verbose: bool [UNTRACKED],
verbose: bool [TRACKED_NO_CRATE_HASH],
}
);
@ -1986,7 +1986,7 @@ written to standard error output)"),
validate_mir: bool = (false, parse_bool, [UNTRACKED],
"validate MIR after each transformation"),
#[rustc_lint_opt_deny_field_access("use `Session::verbose_internals` instead of this field")]
verbose_internals: bool = (false, parse_bool, [UNTRACKED],
verbose_internals: bool = (false, parse_bool, [TRACKED_NO_CRATE_HASH],
"in general, enable more debug printouts (default: no)"),
#[rustc_lint_opt_deny_field_access("use `Session::verify_llvm_ir` instead of this field")]
verify_llvm_ir: bool = (false, parse_bool, [TRACKED],

View File

@ -600,6 +600,7 @@ symbols! {
core_panic_macro,
coroutine,
coroutine_clone,
coroutine_resume,
coroutine_state,
coroutines,
cosf32,

View File

@ -9,10 +9,13 @@
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;
@ -723,6 +726,45 @@ 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,
@ -780,6 +822,15 @@ 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()

View File

@ -245,63 +245,6 @@ fn resolve_associated_item<'tcx>(
span: tcx.def_span(trait_item_id),
})
}
} else if Some(trait_ref.def_id) == lang_items.future_trait() {
let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
bug!()
};
if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
// `Future::poll` is generated by the compiler.
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args })
} else {
// All other methods are default methods of the `Future` trait.
// (this assumes that `ImplSource::Builtin` is only used for methods on `Future`)
debug_assert!(tcx.defaultness(trait_item_id).has_value());
Some(Instance::new(trait_item_id, rcvr_args))
}
} else if Some(trait_ref.def_id) == lang_items.iterator_trait() {
let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
bug!()
};
if Some(trait_item_id) == tcx.lang_items().next_fn() {
// `Iterator::next` is generated by the compiler.
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
} else {
// All other methods are default methods of the `Iterator` trait.
// (this assumes that `ImplSource::Builtin` is only used for methods on `Iterator`)
debug_assert!(tcx.defaultness(trait_item_id).has_value());
Some(Instance::new(trait_item_id, rcvr_args))
}
} else if Some(trait_ref.def_id) == lang_items.async_iterator_trait() {
let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
bug!()
};
if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::poll_next {
span_bug!(
tcx.def_span(coroutine_def_id),
"no definition for `{trait_ref}::{}` for built-in coroutine type",
tcx.item_name(trait_item_id)
)
}
// `AsyncIterator::poll_next` is generated by the compiler.
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
} else if Some(trait_ref.def_id) == lang_items.coroutine_trait() {
let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
bug!()
};
if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume {
// For compiler developers who'd like to add new items to `Coroutine`,
// you either need to generate a shim body, or perhaps return
// `InstanceDef::Item` pointing to a trait default method body if
// it is given a default implementation by the trait.
span_bug!(
tcx.def_span(coroutine_def_id),
"no definition for `{trait_ref}::{}` for built-in coroutine type",
tcx.item_name(trait_item_id)
)
}
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
} else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() {
// FIXME: This doesn't check for malformed libcore that defines, e.g.,
// `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension
@ -334,7 +277,7 @@ fn resolve_associated_item<'tcx>(
),
}
} else {
None
Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args)
}
}
traits::ImplSource::Param(..)

View File

@ -111,6 +111,7 @@ pub trait Coroutine<R = ()> {
/// been returned previously. While coroutine literals in the language are
/// guaranteed to panic on resuming after `Complete`, this is not guaranteed
/// for all implementations of the `Coroutine` trait.
#[cfg_attr(not(bootstrap), lang = "coroutine_resume")]
fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return>;
}

View File

@ -113,6 +113,7 @@
#![feature(slice_flatten)]
#![feature(error_generic_member_access)]
#![feature(error_in_core)]
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
#![feature(utf8_chunks)]
#![feature(is_ascii_octdigit)]
#![feature(get_many_mut)]

View File

@ -191,6 +191,14 @@ impl ToString for TokenStream {
/// Prints the token stream as a string that is supposed to be losslessly convertible back
/// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s
/// with `Delimiter::None` delimiters and negative numeric literals.
///
/// Note: the exact form of the output is subject to change, e.g. there might
/// be changes in the whitespace used between tokens. Therefore, you should
/// *not* do any kind of simple substring matching on the output string (as
/// produced by `to_string`) to implement a proc macro, because that matching
/// might stop working if such changes happen. Instead, you should work at the
/// `TokenTree` level, e.g. matching against `TokenTree::Ident`,
/// `TokenTree::Punct`, or `TokenTree::Literal`.
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl fmt::Display for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -758,6 +766,14 @@ impl ToString for TokenTree {
/// Prints the token tree as a string that is supposed to be losslessly convertible back
/// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s
/// with `Delimiter::None` delimiters and negative numeric literals.
///
/// Note: the exact form of the output is subject to change, e.g. there might
/// be changes in the whitespace used between tokens. Therefore, you should
/// *not* do any kind of simple substring matching on the output string (as
/// produced by `to_string`) to implement a proc macro, because that matching
/// might stop working if such changes happen. Instead, you should work at the
/// `TokenTree` level, e.g. matching against `TokenTree::Ident`,
/// `TokenTree::Punct`, or `TokenTree::Literal`.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Display for TokenTree {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

View File

@ -1,5 +1,3 @@
#![cfg(not(test))]
// These symbols are all defined by `libm`,
// or by `compiler-builtins` on unsupported platforms.

View File

@ -0,0 +1,11 @@
#![cfg(not(test))]
cfg_if::cfg_if! {
if #[cfg(target_os = "windows")] {
mod windows;
pub use windows::*;
} else {
mod builtins;
pub use builtins::*;
}
}

View File

@ -1,5 +1,3 @@
#![cfg(not(test))]
use core::ffi::{c_double, c_float, c_int};
extern "C" {

View File

@ -3,9 +3,11 @@
/// descriptors.
mod pal;
pub mod os_str;
mod personality;
pub mod cmath;
pub mod os_str;
// FIXME(117276): remove this, move feature implementations into individual
// submodules.
pub use pal::*;

View File

@ -19,8 +19,6 @@ use crate::os::raw::c_char;
pub mod alloc;
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod env;
pub mod fd;
pub mod fs;

View File

@ -13,8 +13,6 @@ mod waitqueue;
pub mod alloc;
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod env;
pub mod fd;
#[path = "../unsupported/fs.rs"]

View File

@ -21,8 +21,6 @@ mod itron {
pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod env;
// `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as
// `crate::sys::error`

View File

@ -11,8 +11,6 @@ pub use self::rand::hashmap_random_keys;
pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
#[path = "../unsupported/env.rs"]
pub mod env;
pub mod locks;

View File

@ -14,8 +14,6 @@
pub mod alloc;
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod env;
#[path = "../unsupported/fs.rs"]
pub mod fs;

View File

@ -11,8 +11,6 @@ pub mod weak;
pub mod alloc;
pub mod android;
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod env;
pub mod fd;
pub mod fs;

View File

@ -2,8 +2,6 @@
pub mod alloc;
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod env;
pub mod fs;
pub mod io;

View File

@ -20,8 +20,6 @@ use crate::mem;
#[path = "../unix/alloc.rs"]
pub mod alloc;
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod env;
pub mod fd;
pub mod fs;

View File

@ -19,8 +19,6 @@
pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod env;
#[path = "../unsupported/fs.rs"]
pub mod fs;

View File

@ -97,20 +97,6 @@ unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
return true;
}
// At this point, we *could* have a false negative. We can determine that this is a true
// negative if we can detect the presence of a console on any of the standard I/O streams. If
// another stream has a console, then we know we're in a Windows console and can therefore
// trust the negative.
for std_handle in [c::STD_INPUT_HANDLE, c::STD_OUTPUT_HANDLE, c::STD_ERROR_HANDLE] {
let std_handle = c::GetStdHandle(std_handle);
if !std_handle.is_null()
&& std_handle != handle
&& c::GetConsoleMode(std_handle, &mut out) != 0
{
return false;
}
}
// Otherwise, we fall back to an msys hack to see if we can detect the presence of a pty.
msys_tty_on(handle)
}

View File

@ -15,7 +15,6 @@ pub mod compat;
pub mod alloc;
pub mod args;
pub mod c;
pub mod cmath;
pub mod env;
pub mod fs;
pub mod handle;

View File

@ -3,8 +3,6 @@
pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
#[path = "../unsupported/env.rs"]
pub mod env;
#[path = "../unsupported/fs.rs"]

View File

@ -0,0 +1,27 @@
# `trait_upcasting`
The tracking issue for this feature is: [#65991]
[#65991]: https://github.com/rust-lang/rust/issues/65991
------------------------
The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a
trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo`
so long as `Bar: Foo`.
```rust,edition2018
#![feature(trait_upcasting)]
#![allow(incomplete_features)]
trait Foo {}
trait Bar: Foo {}
impl Foo for i32 {}
impl<T: Foo + ?Sized> Bar for T {}
let bar: &dyn Bar = &123;
let foo: &dyn Foo = bar;
```

View File

@ -10,7 +10,7 @@
#![feature(nonzero_ops)]
#![feature(let_chains)]
#![feature(lint_reasons)]
#![feature(int_roundings)]
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
// Configure clippy and other lints
#![allow(
clippy::collapsible_else_if,

View File

@ -1,3 +1,6 @@
#![feature(trait_upcasting)]
#![allow(incomplete_features)]
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
fn a(&self) -> i32 {
10

View File

@ -1,6 +1,7 @@
//@revisions: stack tree
//@[tree]compile-flags: -Zmiri-tree-borrows
#![feature(allocator_api)]
#![allow(incomplete_features)] // for trait upcasting
#![feature(allocator_api, trait_upcasting)]
use std::alloc::Layout;
use std::alloc::{AllocError, Allocator};

View File

@ -1,3 +1,6 @@
#![feature(trait_upcasting)]
#![allow(incomplete_features)]
fn main() {
basic();
diamond();

View File

@ -11,13 +11,13 @@
#![rustc_partition_codegened(module="commandline_args", cfg="rpass4")]
// Between revisions 1 and 2, we are changing the debuginfo-level, which should
// invalidate the cache. Between revisions 2 and 3, we are adding `--verbose`
// invalidate the cache. Between revisions 2 and 3, we are adding `--diagnostic-width`
// which should have no effect on the cache. Between revisions, we are adding
// `--remap-path-prefix` which should invalidate the cache:
//[rpass1] compile-flags: -C debuginfo=0
//[rpass2] compile-flags: -C debuginfo=2
//[rpass3] compile-flags: -C debuginfo=2 --verbose
//[rpass4] compile-flags: -C debuginfo=2 --verbose --remap-path-prefix=/home/bors/rust=src
//[rpass3] compile-flags: -C debuginfo=2 --diagnostic-width=80
//[rpass4] compile-flags: -C debuginfo=2 --diagnostic-width=80 --remap-path-prefix=/home/bors/r=src
pub fn main() {
// empty

View File

@ -1,4 +1,5 @@
// build-pass
#![feature(trait_upcasting)]
pub trait A {}
pub trait B {}

View File

@ -1,4 +1,4 @@
#![feature(dyn_star)]
#![feature(dyn_star, trait_upcasting)]
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
trait A: B {}

View File

@ -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)]
LL | #![feature(dyn_star, trait_upcasting)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information

View File

@ -1,6 +1,6 @@
// known-bug: #104800
#![feature(dyn_star)]
#![feature(dyn_star, trait_upcasting)]
trait Foo: Bar {
fn hello(&self);

View File

@ -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)]
LL | #![feature(dyn_star, trait_upcasting)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information

View File

@ -0,0 +1,13 @@
trait Foo {}
trait Bar: Foo {}
impl Foo for () {}
impl Bar for () {}
fn main() {
let bar: &dyn Bar = &();
let foo: &dyn Foo = bar;
//~^ ERROR trait upcasting coercion is experimental [E0658]
}

View File

@ -0,0 +1,14 @@
error[E0658]: cannot cast `dyn Bar` to `dyn Foo`, trait upcasting coercion is experimental
--> $DIR/feature-gate-trait_upcasting.rs:11:25
|
LL | let foo: &dyn Foo = bar;
| ^^^
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: required when coercing `&dyn Bar` into `&dyn Foo`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,16 @@
// edition: 2018
// known-bug: #120240
#![feature(never_patterns)]
#![allow(incomplete_features)]
fn main() {}
enum Void {}
// Divergence is not detected.
async fn async_never(!: Void) -> ! {} // gives an error
// Divergence is detected
async fn async_let(x: Void) -> ! {
let ! = x;
}

View File

@ -0,0 +1,12 @@
error[E0308]: mismatched types
--> $DIR/120240-async-fn-never-arg.rs:11:36
|
LL | async fn async_never(!: Void) -> ! {} // gives an error
| ^^ expected `!`, found `()`
|
= note: expected type `!`
found unit type `()`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,36 @@
#![feature(never_patterns)]
#![allow(incomplete_features)]
#![deny(unreachable_patterns)]
#![deny(unreachable_code)]
fn main() {}
enum Void {}
fn never_arg(!: Void) -> u32 {
println!();
//~^ ERROR unreachable statement
}
fn ref_never_arg(&!: &Void) -> u32 {
println!();
//~^ ERROR unreachable statement
}
fn never_let() -> u32 {
let ptr: *const Void = std::ptr::null();
unsafe {
let ! = *ptr;
}
println!();
//~^ ERROR unreachable statement
}
fn never_match() -> u32 {
let ptr: *const Void = std::ptr::null();
unsafe {
match *ptr { ! };
}
println!();
//~^ ERROR unreachable statement
}

View File

@ -0,0 +1,49 @@
error: unreachable statement
--> $DIR/diverge-causes-unreachable-code.rs:11:5
|
LL | fn never_arg(!: Void) -> u32 {
| - any code following a never pattern is unreachable
LL | println!();
| ^^^^^^^^^^ unreachable statement
|
note: the lint level is defined here
--> $DIR/diverge-causes-unreachable-code.rs:4:9
|
LL | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: unreachable statement
--> $DIR/diverge-causes-unreachable-code.rs:16:5
|
LL | fn ref_never_arg(&!: &Void) -> u32 {
| -- any code following a never pattern is unreachable
LL | println!();
| ^^^^^^^^^^ unreachable statement
|
= note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: unreachable statement
--> $DIR/diverge-causes-unreachable-code.rs:25:5
|
LL | let ! = *ptr;
| - any code following a never pattern is unreachable
LL | }
LL | println!();
| ^^^^^^^^^^ unreachable statement
|
= note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: unreachable statement
--> $DIR/diverge-causes-unreachable-code.rs:34:5
|
LL | match *ptr { ! };
| ---------------- any code following this `match` expression is unreachable, as all arms diverge
LL | }
LL | println!();
| ^^^^^^^^^^ unreachable statement
|
= note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors

View File

@ -0,0 +1,56 @@
#![feature(never_patterns)]
#![feature(let_chains)]
#![allow(incomplete_features)]
#![deny(unreachable_patterns)]
fn main() {}
enum Void {}
// Contrast with `./diverges.rs`: merely having an empty type around isn't enough to diverge.
fn wild_void(_: Void) -> u32 {}
//~^ ERROR: mismatched types
fn wild_let() -> u32 {
let ptr: *const Void = std::ptr::null();
unsafe {
//~^ ERROR: mismatched types
let _ = *ptr;
}
}
fn wild_match() -> u32 {
let ptr: *const Void = std::ptr::null();
unsafe {
match *ptr {
_ => {} //~ ERROR: mismatched types
}
}
}
fn binding_void(_x: Void) -> u32 {}
//~^ ERROR: mismatched types
fn binding_let() -> u32 {
let ptr: *const Void = std::ptr::null();
unsafe {
//~^ ERROR: mismatched types
let _x = *ptr;
}
}
fn binding_match() -> u32 {
let ptr: *const Void = std::ptr::null();
unsafe {
match *ptr {
_x => {} //~ ERROR: mismatched types
}
}
}
// Don't confuse this with a `let !` statement.
fn let_chain(x: Void) -> u32 {
if let true = true && let ! = x {}
//~^ ERROR: mismatched types
}

View File

@ -0,0 +1,55 @@
error[E0308]: mismatched types
--> $DIR/diverges-not.rs:12:26
|
LL | fn wild_void(_: Void) -> u32 {}
| --------- ^^^ expected `u32`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
error[E0308]: mismatched types
--> $DIR/diverges-not.rs:17:5
|
LL | / unsafe {
LL | |
LL | | let _ = *ptr;
LL | | }
| |_____^ expected `u32`, found `()`
error[E0308]: mismatched types
--> $DIR/diverges-not.rs:27:18
|
LL | _ => {}
| ^^ expected `u32`, found `()`
error[E0308]: mismatched types
--> $DIR/diverges-not.rs:32:30
|
LL | fn binding_void(_x: Void) -> u32 {}
| ------------ ^^^ expected `u32`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
error[E0308]: mismatched types
--> $DIR/diverges-not.rs:37:5
|
LL | / unsafe {
LL | |
LL | | let _x = *ptr;
LL | | }
| |_____^ expected `u32`, found `()`
error[E0308]: mismatched types
--> $DIR/diverges-not.rs:47:19
|
LL | _x => {}
| ^^ expected `u32`, found `()`
error[E0308]: mismatched types
--> $DIR/diverges-not.rs:54:37
|
LL | if let true = true && let ! = x {}
| ^^ expected `u32`, found `()`
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,38 @@
// check-pass
// edition: 2018
#![feature(never_patterns)]
#![allow(incomplete_features)]
#![deny(unreachable_patterns)]
fn main() {}
enum Void {}
// A never pattern alone diverges.
fn never_arg(!: Void) -> ! {}
fn never_arg_returns_anything<T>(!: Void) -> T {}
fn ref_never_arg(&!: &Void) -> ! {}
fn never_let() -> ! {
let ptr: *const Void = std::ptr::null();
unsafe {
let ! = *ptr;
}
}
fn never_match() -> ! {
let ptr: *const Void = std::ptr::null();
unsafe {
match *ptr { ! };
}
// Ensures this typechecks because of divergence and not the type of the match expression.
println!();
}
// Note: divergence is not detected for async fns when the `!` is in the argument (#120240).
async fn async_let(x: Void) -> ! {
let ! = x;
}

View File

@ -1,5 +1,6 @@
// compile-flags: -Znext-solver
// check-pass
#![feature(trait_upcasting)]
trait A {}
trait B: A {}

View File

@ -1,5 +1,6 @@
// check-pass
// compile-flags: -Znext-solver
#![feature(trait_upcasting)]
pub trait A {}
pub trait B: A {}

View File

@ -1,5 +1,6 @@
// compile-flags: -Znext-solver
// check-pass
#![feature(trait_upcasting)]
trait Foo: Bar<i32> + Bar<u32> {}

View File

@ -1,3 +1,4 @@
#![feature(trait_upcasting)]
#![feature(trait_alias)]
// Although we *elaborate* `T: Alias` to `i32: B`, we should

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/alias-where-clause-isnt-supertrait.rs:26:5
--> $DIR/alias-where-clause-isnt-supertrait.rs:27:5
|
LL | fn test(x: &dyn C) -> &dyn B {
| ------ expected `&dyn B` because of return type

View File

@ -1,5 +1,7 @@
// run-pass
#![feature(trait_upcasting)]
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
fn a(&self) -> i32 {
10

View File

@ -1,4 +1,5 @@
// run-pass
#![feature(trait_upcasting)]
trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {}
trait Bar<T: Default + ToString> {

View File

@ -1,14 +0,0 @@
warning: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/deref-lint-regions.rs:8:1
|
LL | impl<'a> Deref for dyn Foo<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
LL |
LL | type Target = dyn Bar<'a>;
| -------------------------- target type is a supertrait of `dyn Foo<'_>`
|
= help: consider removing this implementation or replacing it with a method instead
= note: `#[warn(deref_into_dyn_supertrait)]` on by default
warning: 1 warning emitted

View File

@ -1,14 +0,0 @@
warning: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/deref-lint.rs:9:1
|
LL | impl<'a> Deref for dyn 'a + B {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
...
LL | type Target = dyn A;
| -------------------- target type is a supertrait of `dyn B`
|
= help: consider removing this implementation or replacing it with a method instead
= note: `#[warn(deref_into_dyn_supertrait)]` on by default
warning: 1 warning emitted

View File

@ -15,6 +15,8 @@ impl Foo for () {
}
impl<'a> Deref for dyn Foo + 'a {
//~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
//~| WARN this will change its meaning in a future release!
type Target = dyn Bar<u32> + 'a;
fn deref(&self) -> &Self::Target {
@ -30,5 +32,4 @@ fn main() {
let x: &dyn Foo = &();
let y = take_dyn(x);
let z: u32 = y;
//~^ ERROR mismatched types
}

View File

@ -1,16 +1,19 @@
error[E0308]: mismatched types
--> $DIR/deref-upcast-behavioral-change.rs:32:18
error: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/deref-upcast-behavioral-change.rs:17:1
|
LL | let z: u32 = y;
| --- ^ expected `u32`, found `i32`
| |
| expected due to this
LL | impl<'a> Deref for dyn Foo + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
...
LL | type Target = dyn Bar<u32> + 'a;
| -------------------------------- target type is a supertrait of `dyn Foo`
|
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
= warning: this will change its meaning in a future release!
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
note: the lint level is defined here
--> $DIR/deref-upcast-behavioral-change.rs:1:9
|
LL | let z: u32 = y.try_into().unwrap();
| ++++++++++++++++++++
LL | #![deny(deref_into_dyn_supertrait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -1,5 +1,7 @@
// run-pass
#![feature(trait_upcasting)]
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
fn a(&self) -> i32 {
10

View File

@ -3,6 +3,8 @@
// revisions: current next
//[next] compile-flags: -Znext-solver
#![feature(trait_upcasting)]
trait A: B {
type Assoc;
}

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/illegal-upcast-from-impl.rs:14:66
--> $DIR/illegal-upcast-from-impl.rs:16:66
|
LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
| ----------------------- ^ expected trait `Super`, found trait `Sub`

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/illegal-upcast-from-impl.rs:14:66
--> $DIR/illegal-upcast-from-impl.rs:16:66
|
LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
| ----------------------- ^ expected trait `Super`, found trait `Sub`

View File

@ -1,6 +1,8 @@
// revisions: current next
//[next] compile-flags: -Znext-solver
#![feature(trait_upcasting)]
trait Super {
type Assoc;
}

View File

@ -1,4 +1,5 @@
#![deny(deref_into_dyn_supertrait)]
#![feature(trait_upcasting)] // remove this and the test compiles
use std::ops::Deref;

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/inference-behavior-change-deref.rs:33:18
--> $DIR/inference-behavior-change-deref.rs:34:18
|
LL | let z: u32 = y;
| --- ^ expected `u32`, found `i32`

View File

@ -1,3 +1,5 @@
#![feature(trait_upcasting)]
trait Foo {
fn a(&self) -> i32 {
10

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:51:35
--> $DIR/invalid-upcast.rs:53:35
|
LL | let _: &dyn std::fmt::Debug = baz;
| -------------------- ^^^ expected trait `Debug`, found trait `Baz`
@ -10,7 +10,7 @@ LL | let _: &dyn std::fmt::Debug = baz;
found reference `&dyn Baz`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:53:24
--> $DIR/invalid-upcast.rs:55:24
|
LL | let _: &dyn Send = baz;
| --------- ^^^ expected trait `Send`, found trait `Baz`
@ -21,7 +21,7 @@ LL | let _: &dyn Send = baz;
found reference `&dyn Baz`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:55:24
--> $DIR/invalid-upcast.rs:57:24
|
LL | let _: &dyn Sync = baz;
| --------- ^^^ expected trait `Sync`, found trait `Baz`
@ -32,7 +32,7 @@ LL | let _: &dyn Sync = baz;
found reference `&dyn Baz`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:58:25
--> $DIR/invalid-upcast.rs:60:25
|
LL | let bar: &dyn Bar = baz;
| -------- ^^^ expected trait `Bar`, found trait `Baz`
@ -43,7 +43,7 @@ LL | let bar: &dyn Bar = baz;
found reference `&dyn Baz`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:60:35
--> $DIR/invalid-upcast.rs:62:35
|
LL | let _: &dyn std::fmt::Debug = bar;
| -------------------- ^^^ expected trait `Debug`, found trait `Bar`
@ -54,7 +54,7 @@ LL | let _: &dyn std::fmt::Debug = bar;
found reference `&dyn Bar`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:62:24
--> $DIR/invalid-upcast.rs:64:24
|
LL | let _: &dyn Send = bar;
| --------- ^^^ expected trait `Send`, found trait `Bar`
@ -65,7 +65,7 @@ LL | let _: &dyn Send = bar;
found reference `&dyn Bar`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:64:24
--> $DIR/invalid-upcast.rs:66:24
|
LL | let _: &dyn Sync = bar;
| --------- ^^^ expected trait `Sync`, found trait `Bar`
@ -76,7 +76,7 @@ LL | let _: &dyn Sync = bar;
found reference `&dyn Bar`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:67:25
--> $DIR/invalid-upcast.rs:69:25
|
LL | let foo: &dyn Foo = baz;
| -------- ^^^ expected trait `Foo`, found trait `Baz`
@ -87,7 +87,7 @@ LL | let foo: &dyn Foo = baz;
found reference `&dyn Baz`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:69:35
--> $DIR/invalid-upcast.rs:71:35
|
LL | let _: &dyn std::fmt::Debug = foo;
| -------------------- ^^^ expected trait `Debug`, found trait `Foo`
@ -98,7 +98,7 @@ LL | let _: &dyn std::fmt::Debug = foo;
found reference `&dyn Foo`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:71:24
--> $DIR/invalid-upcast.rs:73:24
|
LL | let _: &dyn Send = foo;
| --------- ^^^ expected trait `Send`, found trait `Foo`
@ -109,7 +109,7 @@ LL | let _: &dyn Send = foo;
found reference `&dyn Foo`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:73:24
--> $DIR/invalid-upcast.rs:75:24
|
LL | let _: &dyn Sync = foo;
| --------- ^^^ expected trait `Sync`, found trait `Foo`
@ -120,7 +120,7 @@ LL | let _: &dyn Sync = foo;
found reference `&dyn Foo`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:76:25
--> $DIR/invalid-upcast.rs:78:25
|
LL | let foo: &dyn Foo = bar;
| -------- ^^^ expected trait `Foo`, found trait `Bar`
@ -131,7 +131,7 @@ LL | let foo: &dyn Foo = bar;
found reference `&dyn Bar`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:78:35
--> $DIR/invalid-upcast.rs:80:35
|
LL | let _: &dyn std::fmt::Debug = foo;
| -------------------- ^^^ expected trait `Debug`, found trait `Foo`
@ -142,7 +142,7 @@ LL | let _: &dyn std::fmt::Debug = foo;
found reference `&dyn Foo`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:80:24
--> $DIR/invalid-upcast.rs:82:24
|
LL | let _: &dyn Send = foo;
| --------- ^^^ expected trait `Send`, found trait `Foo`
@ -153,7 +153,7 @@ LL | let _: &dyn Send = foo;
found reference `&dyn Foo`
error[E0308]: mismatched types
--> $DIR/invalid-upcast.rs:82:24
--> $DIR/invalid-upcast.rs:84:24
|
LL | let _: &dyn Sync = foo;
| --------- ^^^ expected trait `Sync`, found trait `Foo`

View File

@ -1,4 +1,5 @@
// run-pass
#![feature(trait_upcasting)]
struct Test {
func: Box<dyn FnMut() + 'static>,

View File

@ -0,0 +1,14 @@
error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
--> $DIR/issue-11515.rs:10:38
|
LL | let test = Box::new(Test { func: closure });
| ^^^^^^^
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,14 @@
error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
--> $DIR/issue-11515.rs:10:38
|
LL | let test = Box::new(Test { func: closure });
| ^^^^^^^
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,4 +1,3 @@
// check-pass
// revisions: current next
//[next] compile-flags: -Znext-solver
@ -8,5 +7,5 @@ struct Test {
fn main() {
let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
let test = Box::new(Test { func: closure });
let test = Box::new(Test { func: closure }); //~ ERROR trait upcasting coercion is experimental [E0658]
}

View File

@ -1,5 +1,7 @@
// run-pass
#![feature(trait_upcasting)]
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
fn a(&self) -> i32 {
10

View File

@ -1,4 +1,4 @@
// check-pass
#![deny(deref_into_dyn_supertrait)]
use std::ops::Deref;
@ -6,7 +6,8 @@ trait Bar<'a> {}
trait Foo<'a>: Bar<'a> {}
impl<'a> Deref for dyn Foo<'a> {
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
//~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
//~| WARN this will change its meaning in a future release!
type Target = dyn Bar<'a>;
fn deref(&self) -> &Self::Target {

View File

@ -0,0 +1,19 @@
error: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/migrate-lint-deny-regions.rs:8:1
|
LL | impl<'a> Deref for dyn Foo<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
...
LL | type Target = dyn Bar<'a>;
| -------------------------- target type is a supertrait of `dyn Foo<'_>`
|
= warning: this will change its meaning in a future release!
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
note: the lint level is defined here
--> $DIR/migrate-lint-deny-regions.rs:1:9
|
LL | #![deny(deref_into_dyn_supertrait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -1,4 +1,4 @@
// check-pass
#![deny(deref_into_dyn_supertrait)]
use std::ops::Deref;
@ -7,7 +7,8 @@ trait A {}
trait B: A {}
impl<'a> Deref for dyn 'a + B {
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
//~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
//~| WARN this will change its meaning in a future release!
type Target = dyn A;
fn deref(&self) -> &Self::Target {

View File

@ -0,0 +1,19 @@
error: this `Deref` implementation is covered by an implicit supertrait coercion
--> $DIR/migrate-lint-deny.rs:9:1
|
LL | impl<'a> Deref for dyn 'a + B {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
...
LL | type Target = dyn A;
| -------------------- target type is a supertrait of `dyn B`
|
= warning: this will change its meaning in a future release!
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
note: the lint level is defined here
--> $DIR/migrate-lint-deny.rs:1:9
|
LL | #![deny(deref_into_dyn_supertrait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -10,6 +10,7 @@ trait Foo: Bar<i32> {
impl<'a> Deref for dyn Foo + 'a {
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
//~| WARN this will change its meaning in a future release!
type Target = dyn Bar<u32> + 'a;
fn deref(&self) -> &Self::Target {

View File

@ -3,11 +3,12 @@ warning: this `Deref` implementation is covered by an implicit supertrait coerci
|
LL | impl<'a> Deref for dyn Foo + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
LL |
...
LL | type Target = dyn Bar<u32> + 'a;
| -------------------------------- target type is a supertrait of `dyn Foo`
|
= help: consider removing this implementation or replacing it with a method instead
= warning: this will change its meaning in a future release!
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
= note: `#[warn(deref_into_dyn_supertrait)]` on by default
warning: 1 warning emitted

View File

@ -1,4 +1,5 @@
// check-fail
#![feature(trait_upcasting)]
trait Bar<T> {
fn bar(&self, _: T) {}

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/multiple-occurrence-ambiguousity.rs:19:26
--> $DIR/multiple-occurrence-ambiguousity.rs:20:26
|
LL | let t: &dyn Bar<_> = s;
| ----------- ^ expected trait `Bar`, found trait `Foo`

View File

@ -3,6 +3,8 @@
// revisions: current next
//[next] compile-flags: -Znext-solver
#![feature(trait_upcasting)]
trait Mirror {
type Assoc;
}

View File

@ -1,5 +1,7 @@
// run-pass
#![feature(trait_upcasting)]
trait A {
fn foo_a(&self);
}

View File

@ -1,5 +1,7 @@
// run-pass
#![feature(trait_upcasting)]
use std::rc::Rc;
use std::sync::Arc;

View File

@ -1,3 +1,5 @@
#![feature(trait_upcasting)]
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
fn a(&self) -> i32 {
10

View File

@ -1,64 +1,64 @@
error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope
--> $DIR/subtrait-method.rs:53:9
--> $DIR/subtrait-method.rs:55:9
|
LL | bar.c();
| ^ help: there is a method with a similar name: `a`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Baz` defines an item `c`, perhaps you need to implement it
--> $DIR/subtrait-method.rs:25:1
--> $DIR/subtrait-method.rs:27:1
|
LL | trait Baz: Bar {
| ^^^^^^^^^^^^^^
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
--> $DIR/subtrait-method.rs:57:9
|
LL | foo.b();
| ^ help: there is a method with a similar name: `a`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Bar` defines an item `b`, perhaps you need to implement it
--> $DIR/subtrait-method.rs:15:1
|
LL | trait Bar: Foo {
| ^^^^^^^^^^^^^^
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
--> $DIR/subtrait-method.rs:59:9
|
LL | foo.b();
| ^ help: there is a method with a similar name: `a`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Bar` defines an item `b`, perhaps you need to implement it
--> $DIR/subtrait-method.rs:17:1
|
LL | trait Bar: Foo {
| ^^^^^^^^^^^^^^
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
--> $DIR/subtrait-method.rs:61:9
|
LL | foo.c();
| ^ help: there is a method with a similar name: `a`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Baz` defines an item `c`, perhaps you need to implement it
--> $DIR/subtrait-method.rs:25:1
--> $DIR/subtrait-method.rs:27:1
|
LL | trait Baz: Bar {
| ^^^^^^^^^^^^^^
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
--> $DIR/subtrait-method.rs:63:9
--> $DIR/subtrait-method.rs:65:9
|
LL | foo.b();
| ^ help: there is a method with a similar name: `a`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Bar` defines an item `b`, perhaps you need to implement it
--> $DIR/subtrait-method.rs:15:1
--> $DIR/subtrait-method.rs:17:1
|
LL | trait Bar: Foo {
| ^^^^^^^^^^^^^^
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
--> $DIR/subtrait-method.rs:65:9
--> $DIR/subtrait-method.rs:67:9
|
LL | foo.c();
| ^ help: there is a method with a similar name: `a`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Baz` defines an item `c`, perhaps you need to implement it
--> $DIR/subtrait-method.rs:25:1
--> $DIR/subtrait-method.rs:27:1
|
LL | trait Baz: Bar {
| ^^^^^^^^^^^^^^

View File

@ -1,5 +1,5 @@
error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
--> $DIR/type-checking-test-1.rs:17:13
--> $DIR/type-checking-test-1.rs:19:13
|
LL | let _ = x as &dyn Bar<_>; // Ambiguous
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object

View File

@ -1,5 +1,5 @@
error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
--> $DIR/type-checking-test-1.rs:17:13
--> $DIR/type-checking-test-1.rs:19:13
|
LL | let _ = x as &dyn Bar<_>; // Ambiguous
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object

View File

@ -1,6 +1,8 @@
// revisions: current next
//[next] compile-flags: -Znext-solver
#![feature(trait_upcasting)]
trait Foo: Bar<i32> + Bar<u32> {}
trait Bar<T> {
fn bar(&self) -> Option<T> {

View File

@ -1,3 +1,5 @@
#![feature(trait_upcasting)]
trait Foo<T>: Bar<i32> + Bar<T> {}
trait Bar<T> {
fn bar(&self) -> Option<T> {

Some files were not shown because too many files have changed in this diff Show More