1
Fork 0

Auto merge of #126374 - workingjubilee:rollup-tz0utfr, r=workingjubilee

Rollup of 10 pull requests

Successful merges:

 - #125674 (Rewrite `symlinked-extern`, `symlinked-rlib` and `symlinked-libraries` `run-make` tests in `rmake.rs` format)
 - #125688 (Walk into alias-eq nested goals even if normalization fails)
 - #126142 (Harmonize using root or leaf obligation in trait error reporting)
 - #126303 (Urls to docs in rust_hir)
 - #126328 (Add Option::is_none_or)
 - #126337 (Add test for walking order dependent opaque type behaviour)
 - #126353 (Move `MatchAgainstFreshVars` to old solver)
 - #126356 (docs(rustc): Improve discoverable of Cargo docs)
 - #126358 (safe transmute: support `Single` enums)
 - #126362 (Make `try_from_target_usize` method public)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-06-13 05:00:13 +00:00
commit 56e112afb6
80 changed files with 557 additions and 275 deletions

View file

@ -241,10 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
variant_index: VariantIdx, variant_index: VariantIdx,
) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> { ) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
match self.layout_of(ty)?.variants { match self.layout_of(ty)?.variants {
abi::Variants::Single { index } => { abi::Variants::Single { .. } => Ok(None),
assert_eq!(index, variant_index);
Ok(None)
}
abi::Variants::Multiple { abi::Variants::Multiple {
tag_encoding: TagEncoding::Direct, tag_encoding: TagEncoding::Direct,

View file

@ -1057,7 +1057,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false, ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)), ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)),
ty::Pat(ty, ..) => is_very_trivially_sized(*ty), ty::Pat(ty, ..) => is_very_trivially_sized(*ty),

View file

@ -446,7 +446,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?; let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
// Test bounds. // Test bounds.
// It is sufficient to check this for the end pointer. Also check for overflow! // It is sufficient to check this for the end pointer. Also check for overflow!
if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) { if offset.checked_add(size, &self.tcx).is_none_or(|end| end > alloc_size) {
throw_ub!(PointerOutOfBounds { throw_ub!(PointerOutOfBounds {
alloc_id, alloc_id,
alloc_size, alloc_size,

View file

@ -300,7 +300,7 @@ where
) -> InterpResult<'tcx, P> { ) -> InterpResult<'tcx, P> {
let len = base.len(self)?; // also asserts that we have a type where this makes sense let len = base.len(self)?; // also asserts that we have a type where this makes sense
let actual_to = if from_end { let actual_to = if from_end {
if from.checked_add(to).map_or(true, |to| to > len) { if from.checked_add(to).is_none_or(|to| to > len) {
// This can only be reached in ConstProp and non-rustc-MIR. // This can only be reached in ConstProp and non-rustc-MIR.
throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) }); throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) });
} }

View file

@ -6,6 +6,7 @@
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(is_none_or)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(never_type)] #![feature(never_type)]
#![feature(rustdoc_internals)] #![feature(rustdoc_internals)]

View file

@ -1633,6 +1633,13 @@ pub struct ConstBlock {
} }
/// An expression. /// An expression.
///
/// For more details, see the [rust lang reference].
/// Note that the reference does not document nightly-only features.
/// There may be also slight differences in the names and representation of AST nodes between
/// the compiler and the reference.
///
/// [rust lang reference]: https://doc.rust-lang.org/reference/expressions.html
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Expr<'hir> { pub struct Expr<'hir> {
pub hir_id: HirId, pub hir_id: HirId,
@ -3147,6 +3154,13 @@ impl ItemId {
/// An item /// An item
/// ///
/// The name might be a dummy name in case of anonymous items /// The name might be a dummy name in case of anonymous items
///
/// For more details, see the [rust lang reference].
/// Note that the reference does not document nightly-only features.
/// There may be also slight differences in the names and representation of AST nodes between
/// the compiler and the reference.
///
/// [rust lang reference]: https://doc.rust-lang.org/reference/items.html
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Item<'hir> { pub struct Item<'hir> {
pub ident: Ident, pub ident: Ident,

View file

@ -234,7 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ret_ty = ret_coercion.borrow().expected_ty(); let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.infcx.shallow_resolve(ret_ty); let ret_ty = self.infcx.shallow_resolve(ret_ty);
self.can_coerce(arm_ty, ret_ty) self.can_coerce(arm_ty, ret_ty)
&& prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty)) && prior_arm.is_none_or(|(_, ty, _)| self.can_coerce(ty, ret_ty))
// The match arms need to unify for the case of `impl Trait`. // The match arms need to unify for the case of `impl Trait`.
&& !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..)) && !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
} }

View file

@ -913,7 +913,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
if self if self
.tcx .tcx
.upvars_mentioned(closure_def_id_a.expect_local()) .upvars_mentioned(closure_def_id_a.expect_local())
.map_or(true, |u| u.is_empty()) => .is_none_or(|u| u.is_empty()) =>
{ {
// We coerce the closure, which has fn type // We coerce the closure, which has fn type
// `extern "rust-call" fn((arg0,arg1,...)) -> _` // `extern "rust-call" fn((arg0,arg1,...)) -> _`

View file

@ -1557,7 +1557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
// don't copy that one element, we move it. Only check for Copy if the length is larger. // don't copy that one element, we move it. Only check for Copy if the length is larger.
if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) { if count.try_eval_target_usize(tcx, self.param_env).is_none_or(|len| len > 1) {
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None); let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
let code = traits::ObligationCauseCode::RepeatElementCopy { let code = traits::ObligationCauseCode::RepeatElementCopy {
is_constable, is_constable,

View file

@ -2240,7 +2240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for (idx, (generic_param, param)) in for (idx, (generic_param, param)) in
params_with_generics.iter().enumerate().filter(|(idx, _)| { params_with_generics.iter().enumerate().filter(|(idx, _)| {
check_for_matched_generics check_for_matched_generics
|| expected_idx.map_or(true, |expected_idx| expected_idx == *idx) || expected_idx.is_none_or(|expected_idx| expected_idx == *idx)
}) })
{ {
let Some(generic_param) = generic_param else { let Some(generic_param) = generic_param else {

View file

@ -440,7 +440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
// Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for // Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for
// `as_ref` and `as_deref` compatibility. // `as_ref` and `as_deref` compatibility.
let error_tys_equate_as_ref = error_tys.map_or(true, |(found, expected)| { let error_tys_equate_as_ref = error_tys.is_none_or(|(found, expected)| {
self.can_eq( self.can_eq(
self.param_env, self.param_env,
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, found), Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, found),
@ -492,7 +492,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& Some(adt.did()) == self.tcx.lang_items().string() && Some(adt.did()) == self.tcx.lang_items().string()
&& peeled.is_str() && peeled.is_str()
// `Result::map`, conversely, does not take ref of the error type. // `Result::map`, conversely, does not take ref of the error type.
&& error_tys.map_or(true, |(found, expected)| { && error_tys.is_none_or(|(found, expected)| {
self.can_eq(self.param_env, found, expected) self.can_eq(self.param_env, found, expected)
}) })
{ {

View file

@ -4,6 +4,7 @@
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)] #![feature(control_flow_enum)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(is_none_or)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(never_type)] #![feature(never_type)]
#![feature(try_blocks)] #![feature(try_blocks)]

View file

@ -546,7 +546,7 @@ impl<T> Trait<T> for X {
for pred in hir_generics.bounds_for_param(def_id) { for pred in hir_generics.bounds_for_param(def_id) {
if self.constrain_generic_bound_associated_type_structured_suggestion( if self.constrain_generic_bound_associated_type_structured_suggestion(
diag, diag,
&trait_ref, trait_ref,
pred.bounds, pred.bounds,
assoc, assoc,
assoc_args, assoc_args,
@ -715,7 +715,7 @@ fn foo(&self) -> Self::T { String::new() }
self.constrain_generic_bound_associated_type_structured_suggestion( self.constrain_generic_bound_associated_type_structured_suggestion(
diag, diag,
&trait_ref, trait_ref,
opaque_hir_ty.bounds, opaque_hir_ty.bounds,
assoc, assoc,
assoc_args, assoc_args,
@ -869,7 +869,7 @@ fn foo(&self) -> Self::T { String::new() }
fn constrain_generic_bound_associated_type_structured_suggestion( fn constrain_generic_bound_associated_type_structured_suggestion(
&self, &self,
diag: &mut Diag<'_>, diag: &mut Diag<'_>,
trait_ref: &ty::TraitRef<'tcx>, trait_ref: ty::TraitRef<'tcx>,
bounds: hir::GenericBounds<'_>, bounds: hir::GenericBounds<'_>,
assoc: ty::AssocItem, assoc: ty::AssocItem,
assoc_args: &[ty::GenericArg<'tcx>], assoc_args: &[ty::GenericArg<'tcx>],

View file

@ -4,11 +4,9 @@
pub use rustc_middle::ty::relate::*; pub use rustc_middle::ty::relate::*;
pub use self::_match::MatchAgainstFreshVars;
pub use self::combine::CombineFields; pub use self::combine::CombineFields;
pub use self::combine::PredicateEmittingRelation; pub use self::combine::PredicateEmittingRelation;
pub mod _match;
pub(super) mod combine; pub(super) mod combine;
mod generalize; mod generalize;
mod glb; mod glb;

View file

@ -285,8 +285,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
let obligations = let obligations =
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| { predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
elaboratable.child_with_derived_cause( elaboratable.child_with_derived_cause(
clause clause.instantiate_supertrait(tcx, bound_clause.rebind(data.trait_ref)),
.instantiate_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
span, span,
bound_clause.rebind(data), bound_clause.rebind(data),
index, index,

View file

@ -3257,7 +3257,11 @@ declare_lint! {
/// See the [Checking Conditional Configurations][check-cfg] section for more /// See the [Checking Conditional Configurations][check-cfg] section for more
/// details. /// details.
/// ///
/// See the [Cargo Specifics][unexpected_cfgs_lint_config] section for configuring this lint in
/// `Cargo.toml`.
///
/// [check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html /// [check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html
/// [unexpected_cfgs_lint_config]: https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html#check-cfg-in-lintsrust-table
pub UNEXPECTED_CFGS, pub UNEXPECTED_CFGS,
Warn, Warn,
"detects unexpected names and values in `#[cfg]` conditions", "detects unexpected names and values in `#[cfg]` conditions",

View file

@ -37,7 +37,7 @@ impl<'tcx> Elaborator<'tcx> {
let super_predicates = let super_predicates =
self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map( self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
|&(pred, _)| { |&(pred, _)| {
let clause = pred.instantiate_supertrait(self.tcx, &trait_ref); let clause = pred.instantiate_supertrait(self.tcx, trait_ref);
self.visited.insert(clause).then_some(clause) self.visited.insert(clause).then_some(clause)
}, },
); );

View file

@ -313,7 +313,7 @@ impl<'tcx> Clause<'tcx> {
pub fn instantiate_supertrait( pub fn instantiate_supertrait(
self, self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_ref: &ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
) -> Clause<'tcx> { ) -> Clause<'tcx> {
// The interaction between HRTB and supertraits is not entirely // The interaction between HRTB and supertraits is not entirely
// obvious. Let me walk you (and myself) through an example. // obvious. Let me walk you (and myself) through an example.

View file

@ -48,6 +48,12 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
rhs rhs
}; };
// Add a `make_canonical_response` probe step so that we treat this as
// a candidate, even if `try_evaluate_added_goals` bails due to an error.
// It's `Certainty::AMBIGUOUS` because this candidate is not "finished",
// since equating the normalized terms will lead to additional constraints.
self.inspect.make_canonical_response(Certainty::AMBIGUOUS);
// Apply the constraints. // Apply the constraints.
self.try_evaluate_added_goals()?; self.try_evaluate_added_goals()?;
let lhs = self.resolve_vars_if_possible(lhs); let lhs = self.resolve_vars_if_possible(lhs);

View file

@ -460,9 +460,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
polarity: ty::PredicatePolarity::Positive, polarity: ty::PredicatePolarity::Positive,
})) }))
} }
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => { ty::PredicateKind::Clause(
ChildMode::WellFormedObligation ty::ClauseKind::WellFormed(_) | ty::ClauseKind::Projection(..),
} )
| ty::PredicateKind::AliasRelate(..) => ChildMode::PassThrough,
_ => { _ => {
return ControlFlow::Break(self.obligation.clone()); return ControlFlow::Break(self.obligation.clone());
} }
@ -496,7 +497,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
(_, GoalSource::InstantiateHigherRanked) => { (_, GoalSource::InstantiateHigherRanked) => {
obligation = self.obligation.clone(); obligation = self.obligation.clone();
} }
(ChildMode::WellFormedObligation, _) => { (ChildMode::PassThrough, _) => {
obligation = make_obligation(self.obligation.cause.clone()); obligation = make_obligation(self.obligation.cause.clone());
} }
} }
@ -527,7 +528,7 @@ enum ChildMode<'tcx> {
// Skip trying to derive an `ObligationCause` from this obligation, and // Skip trying to derive an `ObligationCause` from this obligation, and
// report *all* sub-obligations as if they came directly from the parent // report *all* sub-obligations as if they came directly from the parent
// obligation. // obligation.
WellFormedObligation, PassThrough,
} }
fn derive_cause<'tcx>( fn derive_cause<'tcx>(

View file

@ -15,7 +15,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{inspect, QueryResult}; use rustc_middle::traits::solve::{inspect, QueryResult};
use rustc_middle::traits::solve::{Certainty, Goal}; use rustc_middle::traits::solve::{Certainty, Goal, MaybeCause};
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{TyCtxt, TypeFoldable}; use rustc_middle::ty::{TyCtxt, TypeFoldable};
use rustc_middle::{bug, ty}; use rustc_middle::{bug, ty};
@ -291,7 +291,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
steps.push(step) steps.push(step)
} }
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
assert_eq!(shallow_certainty.replace(c), None); assert!(matches!(
shallow_certainty.replace(c),
None | Some(Certainty::Maybe(MaybeCause::Ambiguity))
));
} }
inspect::ProbeStep::NestedProbe(ref probe) => { inspect::ProbeStep::NestedProbe(ref probe) => {
match probe.kind { match probe.kind {

View file

@ -3597,7 +3597,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
trait_ref: &ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
) { ) {
let rhs_span = match obligation.cause.code() { let rhs_span = match obligation.cause.code() {
ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => { ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => {
@ -4592,7 +4592,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) { ) {
if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() { if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() {
return; return;
@ -4602,10 +4602,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let hir::Node::Item(item) = node if let hir::Node::Item(item) = node
&& let hir::ItemKind::Fn(sig, _, body_id) = item.kind && let hir::ItemKind::Fn(sig, _, body_id) = item.kind
&& let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output && let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output
&& self.tcx.is_diagnostic_item(sym::FromResidual, trait_ref.def_id()) && self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id())
&& let ty::Tuple(l) = trait_ref.skip_binder().args.type_at(0).kind() && trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit()
&& l.len() == 0 && let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
&& let ty::Adt(def, _) = trait_ref.skip_binder().args.type_at(1).kind()
&& self.tcx.is_diagnostic_item(sym::Result, def.did()) && self.tcx.is_diagnostic_item(sym::Result, def.did())
{ {
let body = self.tcx.hir().body(body_id); let body = self.tcx.hir().body(body_id);
@ -4863,14 +4862,13 @@ impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
pub(super) fn get_explanation_based_on_obligation<'tcx>( pub(super) fn get_explanation_based_on_obligation<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_predicate: ty::PolyTraitPredicate<'tcx>,
trait_predicate: &ty::PolyTraitPredicate<'tcx>,
pre_message: String, pre_message: String,
) -> String { ) -> String {
if let ObligationCauseCode::MainFunctionType = obligation.cause.code() { if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
"consider using `()`, or a `Result`".to_owned() "consider using `()`, or a `Result`".to_owned()
} else { } else {
let ty_desc = match trait_ref.skip_binder().self_ty().kind() { let ty_desc = match trait_predicate.self_ty().skip_binder().kind() {
ty::FnDef(_, _) => Some("fn item"), ty::FnDef(_, _) => Some("fn item"),
ty::Closure(_, _) => Some("closure"), ty::Closure(_, _) => Some("closure"),
_ => None, _ => None,
@ -4895,7 +4893,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
format!( format!(
"{pre_message}the trait `{}` is not implemented for{desc} `{}`{post}", "{pre_message}the trait `{}` is not implemented for{desc} `{}`{post}",
trait_predicate.print_modifiers_and_trait_path(), trait_predicate.print_modifiers_and_trait_path(),
tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None), tcx.short_ty_string(trait_predicate.self_ty().skip_binder(), &mut None),
) )
} else { } else {
// "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is

View file

@ -412,8 +412,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let bound_predicate = obligation.predicate.kind(); let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() { match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
let trait_predicate = bound_predicate.rebind(trait_predicate); let leaf_trait_predicate =
let trait_predicate = self.resolve_vars_if_possible(trait_predicate); self.resolve_vars_if_possible(bound_predicate.rebind(trait_predicate));
// Let's use the root obligation as the main message, when we care about the // Let's use the root obligation as the main message, when we care about the
// most general case ("X doesn't implement Pattern<'_>") over the case that // most general case ("X doesn't implement Pattern<'_>") over the case that
@ -424,7 +424,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let (main_trait_predicate, o) = if let ty::PredicateKind::Clause( let (main_trait_predicate, o) = if let ty::PredicateKind::Clause(
ty::ClauseKind::Trait(root_pred) ty::ClauseKind::Trait(root_pred)
) = root_obligation.predicate.kind().skip_binder() ) = root_obligation.predicate.kind().skip_binder()
&& !trait_predicate.self_ty().skip_binder().has_escaping_bound_vars() && !leaf_trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()
&& !root_pred.self_ty().has_escaping_bound_vars() && !root_pred.self_ty().has_escaping_bound_vars()
// The type of the leaf predicate is (roughly) the same as the type // The type of the leaf predicate is (roughly) the same as the type
// from the root predicate, as a proxy for "we care about the root" // from the root predicate, as a proxy for "we care about the root"
@ -434,20 +434,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait` // `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait`
self.can_eq( self.can_eq(
obligation.param_env, obligation.param_env,
trait_predicate.self_ty().skip_binder(), leaf_trait_predicate.self_ty().skip_binder(),
root_pred.self_ty().peel_refs(), root_pred.self_ty().peel_refs(),
) )
// `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator` // `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator`
|| self.can_eq( || self.can_eq(
obligation.param_env, obligation.param_env,
trait_predicate.self_ty().skip_binder(), leaf_trait_predicate.self_ty().skip_binder(),
root_pred.self_ty(), root_pred.self_ty(),
) )
) )
// The leaf trait and the root trait are different, so as to avoid // The leaf trait and the root trait are different, so as to avoid
// talking about `&mut T: Trait` and instead remain talking about // talking about `&mut T: Trait` and instead remain talking about
// `T: Trait` instead // `T: Trait` instead
&& trait_predicate.def_id() != root_pred.def_id() && leaf_trait_predicate.def_id() != root_pred.def_id()
// The root trait is not `Unsize`, as to avoid talking about it in // The root trait is not `Unsize`, as to avoid talking about it in
// `tests/ui/coercion/coerce-issue-49593-box-never.rs`. // `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
&& Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait() && Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
@ -459,13 +459,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
root_obligation, root_obligation,
) )
} else { } else {
(trait_predicate, &obligation) (leaf_trait_predicate, &obligation)
}; };
let trait_ref = main_trait_predicate.to_poly_trait_ref(); let main_trait_ref = main_trait_predicate.to_poly_trait_ref();
let leaf_trait_ref = leaf_trait_predicate.to_poly_trait_ref();
if let Some(guar) = self.emit_specialized_closure_kind_error( if let Some(guar) = self.emit_specialized_closure_kind_error(
&obligation, &obligation,
trait_ref, leaf_trait_ref,
) { ) {
return guar; return guar;
} }
@ -473,7 +474,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// FIXME(effects) // FIXME(effects)
let predicate_is_const = false; let predicate_is_const = false;
if let Err(guar) = trait_predicate.error_reported() if let Err(guar) = leaf_trait_predicate.error_reported()
{ {
return guar; return guar;
} }
@ -507,16 +508,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
notes, notes,
parent_label, parent_label,
append_const_msg, append_const_msg,
} = self.on_unimplemented_note(trait_ref, o, &mut long_ty_file); } = self.on_unimplemented_note(main_trait_ref, o, &mut long_ty_file);
let have_alt_message = message.is_some() || label.is_some(); let have_alt_message = message.is_some() || label.is_some();
let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id());
let is_unsize = let is_unsize =
Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); Some(leaf_trait_ref.def_id()) == self.tcx.lang_items().unsize_trait();
let (message, notes, append_const_msg) = if is_try_conversion { let (message, notes, append_const_msg) = if is_try_conversion {
( (
Some(format!( Some(format!(
"`?` couldn't convert the error to `{}`", "`?` couldn't convert the error to `{}`",
trait_ref.skip_binder().self_ty(), main_trait_ref.skip_binder().self_ty(),
)), )),
vec![ vec![
"the question mark operation (`?`) implicitly performs a \ "the question mark operation (`?`) implicitly performs a \
@ -530,20 +532,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}; };
let err_msg = self.get_standard_error_message( let err_msg = self.get_standard_error_message(
&main_trait_predicate, main_trait_predicate,
message, message,
predicate_is_const, predicate_is_const,
append_const_msg, append_const_msg,
post_message, post_message,
); );
let (err_msg, safe_transmute_explanation) = if Some(trait_ref.def_id()) let (err_msg, safe_transmute_explanation) = if Some(main_trait_ref.def_id())
== self.tcx.lang_items().transmute_trait() == self.tcx.lang_items().transmute_trait()
{ {
// Recompute the safe transmute reason and use that for the error reporting // Recompute the safe transmute reason and use that for the error reporting
match self.get_safe_transmute_error_and_reason( match self.get_safe_transmute_error_and_reason(
obligation.clone(), obligation.clone(),
trait_ref, main_trait_ref,
span, span,
) { ) {
GetSafeTransmuteErrorAndReason::Silent => { GetSafeTransmuteErrorAndReason::Silent => {
@ -571,7 +573,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} }
let mut suggested = false; let mut suggested = false;
if is_try_conversion { if is_try_conversion {
suggested = self.try_conversion_context(&obligation, trait_ref.skip_binder(), &mut err); suggested = self.try_conversion_context(&obligation, main_trait_ref.skip_binder(), &mut err);
} }
if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) { if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) {
@ -579,19 +581,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ret_span, ret_span,
format!( format!(
"expected `{}` because of this", "expected `{}` because of this",
trait_ref.skip_binder().self_ty() main_trait_ref.skip_binder().self_ty()
), ),
); );
} }
if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() { if Some(leaf_trait_ref.def_id()) == tcx.lang_items().tuple_trait() {
self.add_tuple_trait_message( self.add_tuple_trait_message(
obligation.cause.code().peel_derives(), obligation.cause.code().peel_derives(),
&mut err, &mut err,
); );
} }
if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait() if Some(leaf_trait_ref.def_id()) == tcx.lang_items().drop_trait()
&& predicate_is_const && predicate_is_const
{ {
err.note("`~const Drop` was renamed to `~const Destruct`"); err.note("`~const Drop` was renamed to `~const Destruct`");
@ -601,24 +603,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let explanation = get_explanation_based_on_obligation( let explanation = get_explanation_based_on_obligation(
self.tcx, self.tcx,
&obligation, &obligation,
trait_ref, leaf_trait_predicate,
&trait_predicate,
pre_message, pre_message,
); );
self.check_for_binding_assigned_block_without_tail_expression( self.check_for_binding_assigned_block_without_tail_expression(
&obligation, &obligation,
&mut err, &mut err,
trait_predicate, leaf_trait_predicate,
); );
self.suggest_add_result_as_return_type(&obligation, self.suggest_add_result_as_return_type(
&obligation,
&mut err, &mut err,
trait_ref); leaf_trait_predicate,
);
if self.suggest_add_reference_to_arg( if self.suggest_add_reference_to_arg(
&obligation, &obligation,
&mut err, &mut err,
trait_predicate, leaf_trait_predicate,
have_alt_message, have_alt_message,
) { ) {
self.note_obligation_cause(&mut err, &obligation); self.note_obligation_cause(&mut err, &obligation);
@ -630,7 +633,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// If it has a custom `#[rustc_on_unimplemented]` // If it has a custom `#[rustc_on_unimplemented]`
// error message, let's display it as the label! // error message, let's display it as the label!
err.span_label(span, s); err.span_label(span, s);
if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { if !matches!(leaf_trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
// When the self type is a type param We don't need to "the trait // When the self type is a type param We don't need to "the trait
// `std::marker::Sized` is not implemented for `T`" as we will point // `std::marker::Sized` is not implemented for `T`" as we will point
// at the type param with a label to suggest constraining it. // at the type param with a label to suggest constraining it.
@ -645,7 +648,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let ObligationCauseCode::Coercion { source, target } = if let ObligationCauseCode::Coercion { source, target } =
*obligation.cause.code().peel_derives() *obligation.cause.code().peel_derives()
{ {
if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { if Some(leaf_trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
self.suggest_borrowing_for_object_cast( self.suggest_borrowing_for_object_cast(
&mut err, &mut err,
root_obligation, root_obligation,
@ -657,7 +660,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let UnsatisfiedConst(unsatisfied_const) = self let UnsatisfiedConst(unsatisfied_const) = self
.maybe_add_note_for_unsatisfied_const( .maybe_add_note_for_unsatisfied_const(
&trait_predicate, leaf_trait_predicate,
&mut err, &mut err,
span, span,
); );
@ -674,15 +677,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err.span_label(tcx.def_span(body), s); err.span_label(tcx.def_span(body), s);
} }
self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref); self.suggest_floating_point_literal(&obligation, &mut err, leaf_trait_ref);
self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate); self.suggest_dereferencing_index(&obligation, &mut err, leaf_trait_predicate);
suggested |= self.suggest_dereferences(&obligation, &mut err, trait_predicate); suggested |= self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate);
suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); suggested |= self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate);
let impl_candidates = self.find_similar_impl_candidates(trait_predicate); let impl_candidates = self.find_similar_impl_candidates(leaf_trait_predicate);
suggested = if let &[cand] = &impl_candidates[..] { suggested = if let &[cand] = &impl_candidates[..] {
let cand = cand.trait_ref; let cand = cand.trait_ref;
if let (ty::FnPtr(_), ty::FnDef(..)) = if let (ty::FnPtr(_), ty::FnDef(..)) =
(cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) (cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind())
{ {
err.span_suggestion( err.span_suggestion(
span.shrink_to_hi(), span.shrink_to_hi(),
@ -702,31 +705,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
false false
} || suggested; } || suggested;
suggested |= suggested |=
self.suggest_remove_reference(&obligation, &mut err, trait_predicate); self.suggest_remove_reference(&obligation, &mut err, leaf_trait_predicate);
suggested |= self.suggest_semicolon_removal( suggested |= self.suggest_semicolon_removal(
&obligation, &obligation,
&mut err, &mut err,
span, span,
trait_predicate, leaf_trait_predicate,
); );
self.note_version_mismatch(&mut err, &trait_ref); self.note_version_mismatch(&mut err, leaf_trait_ref);
self.suggest_remove_await(&obligation, &mut err); self.suggest_remove_await(&obligation, &mut err);
self.suggest_derive(&obligation, &mut err, trait_predicate); self.suggest_derive(&obligation, &mut err, leaf_trait_predicate);
if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { if Some(leaf_trait_ref.def_id()) == tcx.lang_items().try_trait() {
self.suggest_await_before_try( self.suggest_await_before_try(
&mut err, &mut err,
&obligation, &obligation,
trait_predicate, leaf_trait_predicate,
span, span,
); );
} }
if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) { if self.suggest_add_clone_to_arg(&obligation, &mut err, leaf_trait_predicate) {
return err.emit(); return err.emit();
} }
if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) { if self.suggest_impl_trait(&mut err, &obligation, leaf_trait_predicate) {
return err.emit(); return err.emit();
} }
@ -741,9 +744,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
); );
} }
let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id()); let is_fn_trait = tcx.is_fn_trait(leaf_trait_ref.def_id());
let is_target_feature_fn = if let ty::FnDef(def_id, _) = let is_target_feature_fn = if let ty::FnDef(def_id, _) =
*trait_ref.skip_binder().self_ty().kind() *leaf_trait_ref.skip_binder().self_ty().kind()
{ {
!self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
} else { } else {
@ -757,8 +760,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.try_to_add_help_message( self.try_to_add_help_message(
&obligation, &obligation,
trait_ref, leaf_trait_predicate,
&trait_predicate,
&mut err, &mut err,
span, span,
is_fn_trait, is_fn_trait,
@ -769,17 +771,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// Changing mutability doesn't make a difference to whether we have // Changing mutability doesn't make a difference to whether we have
// an `Unsize` impl (Fixes ICE in #71036) // an `Unsize` impl (Fixes ICE in #71036)
if !is_unsize { if !is_unsize {
self.suggest_change_mut(&obligation, &mut err, trait_predicate); self.suggest_change_mut(&obligation, &mut err, leaf_trait_predicate);
} }
// If this error is due to `!: Trait` not implemented but `(): Trait` is // If this error is due to `!: Trait` not implemented but `(): Trait` is
// implemented, and fallback has occurred, then it could be due to a // implemented, and fallback has occurred, then it could be due to a
// variable that used to fallback to `()` now falling back to `!`. Issue a // variable that used to fallback to `()` now falling back to `!`. Issue a
// note informing about the change in behaviour. // note informing about the change in behaviour.
if trait_predicate.skip_binder().self_ty().is_never() if leaf_trait_predicate.skip_binder().self_ty().is_never()
&& self.fallback_has_occurred && self.fallback_has_occurred
{ {
let predicate = trait_predicate.map_bound(|trait_pred| { let predicate = leaf_trait_predicate.map_bound(|trait_pred| {
trait_pred.with_self_ty(self.tcx, tcx.types.unit) trait_pred.with_self_ty(self.tcx, tcx.types.unit)
}); });
let unit_obligation = obligation.with(tcx, predicate); let unit_obligation = obligation.with(tcx, predicate);
@ -794,8 +796,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} }
} }
self.explain_hrtb_projection(&mut err, trait_predicate, obligation.param_env, &obligation.cause); self.explain_hrtb_projection(&mut err, leaf_trait_predicate, obligation.param_env, &obligation.cause);
self.suggest_desugaring_async_fn_in_trait(&mut err, trait_ref); self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_ref);
// Return early if the trait is Debug or Display and the invocation // Return early if the trait is Debug or Display and the invocation
// originates within a standard library macro, because the output // originates within a standard library macro, because the output
@ -813,15 +815,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if in_std_macro if in_std_macro
&& matches!( && matches!(
self.tcx.get_diagnostic_name(trait_ref.def_id()), self.tcx.get_diagnostic_name(leaf_trait_ref.def_id()),
Some(sym::Debug | sym::Display) Some(sym::Debug | sym::Display)
) )
{ {
return err.emit(); return err.emit();
} }
err err
} }
@ -2236,11 +2236,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
/// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
/// with the same path as `trait_ref`, a help message about /// with the same path as `trait_ref`, a help message about
/// a probable version mismatch is added to `err` /// a probable version mismatch is added to `err`
fn note_version_mismatch( fn note_version_mismatch(&self, err: &mut Diag<'_>, trait_ref: ty::PolyTraitRef<'tcx>) -> bool {
&self,
err: &mut Diag<'_>,
trait_ref: &ty::PolyTraitRef<'tcx>,
) -> bool {
let get_trait_impls = |trait_def_id| { let get_trait_impls = |trait_def_id| {
let mut trait_impls = vec![]; let mut trait_impls = vec![];
self.tcx.for_each_relevant_impl( self.tcx.for_each_relevant_impl(
@ -2705,6 +2701,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
), ),
); );
} }
ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
if term.is_infer() =>
{
if let Some(e) = self.tainted_by_errors() {
return e;
}
struct_span_code_err!(
self.dcx(),
span,
E0284,
"type annotations needed: cannot normalize `{alias}`",
)
.with_span_label(span, format!("cannot normalize `{alias}`"))
}
_ => { _ => {
if let Some(e) = self.tainted_by_errors() { if let Some(e) = self.tainted_by_errors() {
return e; return e;
@ -3044,7 +3056,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn get_standard_error_message( fn get_standard_error_message(
&self, &self,
trait_predicate: &ty::PolyTraitPredicate<'tcx>, trait_predicate: ty::PolyTraitPredicate<'tcx>,
message: Option<String>, message: Option<String>,
predicate_is_const: bool, predicate_is_const: bool,
append_const_msg: Option<AppendConstMessage>, append_const_msg: Option<AppendConstMessage>,
@ -3215,8 +3227,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn try_to_add_help_message( fn try_to_add_help_message(
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_predicate: ty::PolyTraitPredicate<'tcx>,
trait_predicate: &ty::PolyTraitPredicate<'tcx>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
span: Span, span: Span,
is_fn_trait: bool, is_fn_trait: bool,
@ -3233,16 +3244,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}; };
// Try to report a help message // Try to report a help message
let trait_def_id = trait_predicate.def_id();
if is_fn_trait if is_fn_trait
&& let Ok((implemented_kind, params)) = self.type_implements_fn_trait( && let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
obligation.param_env, obligation.param_env,
trait_ref.self_ty(), trait_predicate.self_ty(),
trait_predicate.skip_binder().polarity, trait_predicate.skip_binder().polarity,
) )
{ {
self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params); self.add_help_message_for_fn_trait(
} else if !trait_ref.has_non_region_infer() trait_predicate.to_poly_trait_ref(),
&& self.predicate_can_apply(obligation.param_env, *trait_predicate) err,
implemented_kind,
params,
);
} else if !trait_predicate.has_non_region_infer()
&& self.predicate_can_apply(obligation.param_env, trait_predicate)
{ {
// If a where-clause may be useful, remind the // If a where-clause may be useful, remind the
// user that they can add it. // user that they can add it.
@ -3253,25 +3270,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// which is somewhat confusing. // which is somewhat confusing.
self.suggest_restricting_param_bound( self.suggest_restricting_param_bound(
err, err,
*trait_predicate, trait_predicate,
None, None,
obligation.cause.body_id, obligation.cause.body_id,
); );
} else if trait_ref.def_id().is_local() } else if trait_def_id.is_local()
&& self.tcx.trait_impls_of(trait_ref.def_id()).is_empty() && self.tcx.trait_impls_of(trait_def_id).is_empty()
&& !self.tcx.trait_is_auto(trait_ref.def_id()) && !self.tcx.trait_is_auto(trait_def_id)
&& !self.tcx.trait_is_alias(trait_ref.def_id()) && !self.tcx.trait_is_alias(trait_def_id)
{ {
err.span_help( err.span_help(
self.tcx.def_span(trait_ref.def_id()), self.tcx.def_span(trait_def_id),
crate::fluent_generated::trait_selection_trait_has_no_impls, crate::fluent_generated::trait_selection_trait_has_no_impls,
); );
} else if !suggested && !unsatisfied_const { } else if !suggested && !unsatisfied_const {
// Can't show anything else useful, try to find similar impls. // Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(*trait_predicate); let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
if !self.report_similar_impl_candidates( if !self.report_similar_impl_candidates(
&impl_candidates, &impl_candidates,
trait_ref, trait_predicate.to_poly_trait_ref(),
body_def_id, body_def_id,
err, err,
true, true,
@ -3279,7 +3296,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
) { ) {
self.report_similar_impl_candidates_for_root_obligation( self.report_similar_impl_candidates_for_root_obligation(
obligation, obligation,
*trait_predicate, trait_predicate,
body_def_id, body_def_id,
err, err,
); );
@ -3288,7 +3305,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.suggest_convert_to_slice( self.suggest_convert_to_slice(
err, err,
obligation, obligation,
trait_ref, trait_predicate.to_poly_trait_ref(),
impl_candidates.as_slice(), impl_candidates.as_slice(),
span, span,
); );
@ -3353,7 +3370,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn maybe_add_note_for_unsatisfied_const( fn maybe_add_note_for_unsatisfied_const(
&self, &self,
_trait_predicate: &ty::PolyTraitPredicate<'tcx>, _trait_predicate: ty::PolyTraitPredicate<'tcx>,
_err: &mut Diag<'_>, _err: &mut Diag<'_>,
_span: Span, _span: Span,
) -> UnsatisfiedConst { ) -> UnsatisfiedConst {

View file

@ -194,7 +194,7 @@ fn predicates_reference_self(
predicates predicates
.predicates .predicates
.iter() .iter()
.map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, &trait_ref), sp)) .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
.filter_map(|predicate| predicate_references_self(tcx, predicate)) .filter_map(|predicate| predicate_references_self(tcx, predicate))
.collect() .collect()
} }

View file

@ -1,10 +1,10 @@
use rustc_infer::infer::relate::{
self, structurally_relate_tys, Relate, RelateResult, TypeRelation,
};
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use super::{structurally_relate_tys, Relate, RelateResult, TypeRelation};
use crate::infer::relate;
/// A type "A" *matches* "B" if the fresh types in B could be /// A type "A" *matches* "B" if the fresh types in B could be
/// instantiated with values so as to make it equal to A. Matching is /// instantiated with values so as to make it equal to A. Matching is
/// intended to be used only on freshened types, and it basically /// intended to be used only on freshened types, and it basically

View file

@ -32,7 +32,6 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Diag, EmissionGuarantee}; use rustc_errors::{Diag, EmissionGuarantee};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::infer::relate::MatchAgainstFreshVars;
use rustc_infer::infer::relate::TypeRelation; use rustc_infer::infer::relate::TypeRelation;
use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::infer::BoundRegionConversionTime;
use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
@ -60,6 +59,7 @@ use std::ops::ControlFlow;
pub use rustc_middle::traits::select::*; pub use rustc_middle::traits::select::*;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
mod _match;
mod candidate_assembly; mod candidate_assembly;
mod confirmation; mod confirmation;
@ -1866,7 +1866,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
// the param_env so that it can be given the lowest priority. See // the param_env so that it can be given the lowest priority. See
// #50825 for the motivation for this. // #50825 for the motivation for this.
let is_global = let is_global =
|cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars(); |cand: ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
// `DiscriminantKindCandidate`, `ConstDestructCandidate` // `DiscriminantKindCandidate`, `ConstDestructCandidate`
@ -1909,7 +1909,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
} }
( (
ParamCandidate(ref other_cand), ParamCandidate(other_cand),
ImplCandidate(..) ImplCandidate(..)
| AutoImplCandidate | AutoImplCandidate
| ClosureCandidate { .. } | ClosureCandidate { .. }
@ -1934,12 +1934,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
// //
// Global bounds from the where clause should be ignored // Global bounds from the where clause should be ignored
// here (see issue #50825). // here (see issue #50825).
DropVictim::drop_if(!is_global(other_cand)) DropVictim::drop_if(!is_global(*other_cand))
} }
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => { (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(victim_cand)) => {
// Prefer these to a global where-clause bound // Prefer these to a global where-clause bound
// (see issue #50825). // (see issue #50825).
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No } if is_global(*victim_cand) { DropVictim::Yes } else { DropVictim::No }
} }
( (
ImplCandidate(_) ImplCandidate(_)
@ -1957,12 +1957,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
| TraitUpcastingUnsizeCandidate(_) | TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true } | BuiltinCandidate { has_nested: true }
| TraitAliasCandidate, | TraitAliasCandidate,
ParamCandidate(ref victim_cand), ParamCandidate(victim_cand),
) => { ) => {
// Prefer these to a global where-clause bound // Prefer these to a global where-clause bound
// (see issue #50825). // (see issue #50825).
DropVictim::drop_if( DropVictim::drop_if(
is_global(victim_cand) && other.evaluation.must_apply_modulo_regions(), is_global(*victim_cand) && other.evaluation.must_apply_modulo_regions(),
) )
} }
@ -2719,7 +2719,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
previous: ty::PolyTraitPredicate<'tcx>, previous: ty::PolyTraitPredicate<'tcx>,
current: ty::PolyTraitPredicate<'tcx>, current: ty::PolyTraitPredicate<'tcx>,
) -> bool { ) -> bool {
let mut matcher = MatchAgainstFreshVars::new(self.tcx()); let mut matcher = _match::MatchAgainstFreshVars::new(self.tcx());
matcher.relate(previous, current).is_ok() matcher.relate(previous, current).is_ok()
} }

View file

@ -132,7 +132,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
debug!(?predicates); debug!(?predicates);
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
pred.instantiate_supertrait(tcx, &trait_ref) pred.instantiate_supertrait(tcx, trait_ref)
.as_trait_clause() .as_trait_clause()
.map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span))
}); });

View file

@ -125,7 +125,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
.predicates .predicates
.into_iter() .into_iter()
.filter_map(move |(pred, _)| { .filter_map(move |(pred, _)| {
pred.instantiate_supertrait(tcx, &inner_most_trait_ref).as_trait_clause() pred.instantiate_supertrait(tcx, inner_most_trait_ref).as_trait_clause()
}); });
// Find an unvisited supertrait // Find an unvisited supertrait

View file

@ -331,30 +331,63 @@ pub(crate) mod rustc {
assert!(def.is_enum()); assert!(def.is_enum());
let layout = ty_and_layout.layout; let layout = ty_and_layout.layout;
if let Variants::Multiple { tag_field, .. } = layout.variants() { // Computes the variant of a given index.
// For enums (but not coroutines), the tag field is let layout_of_variant = |index| {
// currently always the first field of the layout. let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, index));
assert_eq!(*tag_field, 0); let variant_def = Def::Variant(def.variant(index));
} let variant_ty_and_layout = ty_and_layout.for_variant(&cx, index);
Self::from_variant(variant_def, tag, variant_ty_and_layout, layout.size, cx)
};
let variants = def.discriminants(cx.tcx()).try_fold( // We consider three kinds of enums, each demanding a different
Self::uninhabited(), // treatment of their layout computation:
|variants, (idx, ref discriminant)| { // 1. enums that are uninhabited
let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, idx)); // 2. enums for which all but one variant is uninhabited
let variant_def = Def::Variant(def.variant(idx)); // 3. enums with multiple inhabited variants
let variant_ty_and_layout = ty_and_layout.for_variant(&cx, idx); match layout.variants() {
let variant = Self::from_variant( _ if layout.abi.is_uninhabited() => {
variant_def, // Uninhabited enums are usually (always?) zero-sized. In
tag, // the (unlikely?) event that an uninhabited enum is
variant_ty_and_layout, // non-zero-sized, this assert will trigger an ICE, and this
layout.size, // code should be modified such that a `layout.size` amount
cx, // of uninhabited bytes is returned instead.
//
// Uninhabited enums are currently implemented such that
// their layout is described with `Variants::Single`, even
// though they don't necessarily have a 'single' variant to
// defer to. That said, we don't bother specifically
// matching on `Variants::Single` in this arm because the
// behavioral principles here remain true even if, for
// whatever reason, the compiler describes an uninhabited
// enum with `Variants::Multiple`.
assert_eq!(layout.size, Size::ZERO);
Ok(Self::uninhabited())
}
Variants::Single { index } => {
// `Variants::Single` on non-uninhabited enums denotes that
// the enum delegates its layout to the variant at `index`.
layout_of_variant(*index)
}
Variants::Multiple { tag_field, .. } => {
// `Variants::Multiple` denotes an enum with multiple
// inhabited variants. The layout of such an enum is the
// disjunction of the layouts of its tagged variants.
// For enums (but not coroutines), the tag field is
// currently always the first field of the layout.
assert_eq!(*tag_field, 0);
let variants = def.discriminants(cx.tcx()).try_fold(
Self::uninhabited(),
|variants, (idx, ref discriminant)| {
let variant = layout_of_variant(idx)?;
Result::<Self, Err>::Ok(variants.or(variant))
},
)?; )?;
Result::<Self, Err>::Ok(variants.or(variant))
},
)?;
return Ok(Self::def(Def::Adt(def)).then(variants)); return Ok(Self::def(Def::Adt(def)).then(variants));
}
}
} }
/// Constructs a `Tree` from a 'variant-like' layout. /// Constructs a `Tree` from a 'variant-like' layout.

View file

@ -122,7 +122,7 @@ impl TyConst {
} }
/// Creates an interned usize constant. /// Creates an interned usize constant.
fn try_from_target_usize(val: u64) -> Result<Self, Error> { pub fn try_from_target_usize(val: u64) -> Result<Self, Error> {
with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize)) with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize))
} }

View file

@ -654,6 +654,32 @@ impl<T> Option<T> {
!self.is_some() !self.is_some()
} }
/// Returns `true` if the option is a [`None`] or the value inside of it matches a predicate.
///
/// # Examples
///
/// ```
/// #![feature(is_none_or)]
///
/// let x: Option<u32> = Some(2);
/// assert_eq!(x.is_none_or(|x| x > 1), true);
///
/// let x: Option<u32> = Some(0);
/// assert_eq!(x.is_none_or(|x| x > 1), false);
///
/// let x: Option<u32> = None;
/// assert_eq!(x.is_none_or(|x| x > 1), true);
/// ```
#[must_use]
#[inline]
#[unstable(feature = "is_none_or", issue = "none")]
pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
match self {
None => true,
Some(x) => f(x),
}
}
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// Adapter for working with references // Adapter for working with references
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////

View file

@ -11,8 +11,8 @@ development process.
In order to accomplish that goal, `rustc` accepts the `--check-cfg` flag, which specifies In order to accomplish that goal, `rustc` accepts the `--check-cfg` flag, which specifies
whether to check conditions and how to check them. whether to check conditions and how to check them.
> **Note:** No implicit expectation is added when using `--cfg`. Users are expected to > **Note:** For interacting with this through Cargo,
pass all expected names and values using the _check cfg specification_. see [Cargo Specifics](check-cfg/cargo-specifics.md) page.
[^reachable]: `rustc` promises to at least check reachable `#[cfg]`, and while non-reachable [^reachable]: `rustc` promises to at least check reachable `#[cfg]`, and while non-reachable
`#[cfg]` are not currently checked, they may well be checked in the future without it being a `#[cfg]` are not currently checked, they may well be checked in the future without it being a
@ -23,6 +23,9 @@ breaking change.
To specify expected names and values, the _check cfg specification_ provides the `cfg(...)` To specify expected names and values, the _check cfg specification_ provides the `cfg(...)`
option which enables specifying for an expected config name and it's expected values. option which enables specifying for an expected config name and it's expected values.
> **Note:** No implicit expectation is added when using `--cfg`. Users are expected to
pass all expected names and values using the _check cfg specification_.
It has this basic form: It has this basic form:
```bash ```bash

View file

@ -13,6 +13,7 @@
#![feature(lint_reasons)] #![feature(lint_reasons)]
#![feature(trait_upcasting)] #![feature(trait_upcasting)]
#![feature(strict_overflow_ops)] #![feature(strict_overflow_ops)]
#![feature(is_none_or)]
// Configure clippy and other lints // Configure clippy and other lints
#![allow( #![allow(
clippy::collapsible_else_if, clippy::collapsible_else_if,

View file

@ -396,12 +396,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// If the newly promised alignment is bigger than the native alignment of this // If the newly promised alignment is bigger than the native alignment of this
// allocation, and bigger than the previously promised alignment, then set it. // allocation, and bigger than the previously promised alignment, then set it.
if align > alloc_align if align > alloc_align
&& !this && this
.machine .machine
.symbolic_alignment .symbolic_alignment
.get_mut() .get_mut()
.get(&alloc_id) .get(&alloc_id)
.is_some_and(|&(_, old_align)| align <= old_align) .is_none_or(|&(_, old_align)| align > old_align)
{ {
this.machine.symbolic_alignment.get_mut().insert(alloc_id, (offset, align)); this.machine.symbolic_alignment.get_mut().insert(alloc_id, (offset, align));
} }

View file

@ -95,6 +95,34 @@ pub fn source_root() -> PathBuf {
env_var("SOURCE_ROOT").into() env_var("SOURCE_ROOT").into()
} }
/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
#[cfg(target_family = "windows")]
pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
if link.as_ref().exists() {
std::fs::remove_dir(link.as_ref()).unwrap();
}
use std::os::windows::fs;
fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!(
"failed to create symlink {:?} for {:?}",
link.as_ref().display(),
original.as_ref().display(),
));
}
/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
#[cfg(target_family = "unix")]
pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
if link.as_ref().exists() {
std::fs::remove_dir(link.as_ref()).unwrap();
}
use std::os::unix::fs;
fs::symlink(original.as_ref(), link.as_ref()).expect(&format!(
"failed to create symlink {:?} for {:?}",
link.as_ref().display(),
original.as_ref().display(),
));
}
/// Construct the static library name based on the platform. /// Construct the static library name based on the platform.
pub fn static_lib_name(name: &str) -> String { pub fn static_lib_name(name: &str) -> String {
// See tools.mk (irrelevant lines omitted): // See tools.mk (irrelevant lines omitted):

View file

@ -1387,6 +1387,7 @@ fn generic_args_sans_defaults<'ga>(
} }
// otherwise, if the arg is equal to the param default, hide it (unless the // otherwise, if the arg is equal to the param default, hide it (unless the
// default is an error which can happen for the trait Self type) // default is an error which can happen for the trait Self type)
#[allow(unstable_name_collisions)]
default_parameters.get(i).is_none_or(|default_parameter| { default_parameters.get(i).is_none_or(|default_parameter| {
// !is_err(default_parameter.skip_binders()) // !is_err(default_parameter.skip_binders())
// && // &&

View file

@ -226,9 +226,6 @@ run-make/std-core-cycle/Makefile
run-make/symbol-mangling-hashed/Makefile run-make/symbol-mangling-hashed/Makefile
run-make/symbol-visibility/Makefile run-make/symbol-visibility/Makefile
run-make/symbols-include-type-name/Makefile run-make/symbols-include-type-name/Makefile
run-make/symlinked-extern/Makefile
run-make/symlinked-libraries/Makefile
run-make/symlinked-rlib/Makefile
run-make/sysroot-crates-are-unstable/Makefile run-make/sysroot-crates-are-unstable/Makefile
run-make/target-cpu-native/Makefile run-make/target-cpu-native/Makefile
run-make/target-specs/Makefile run-make/target-specs/Makefile

View file

@ -1,34 +0,0 @@
//@ known-bug: rust-lang/rust#125811
mod assert {
use std::mem::{Assume, BikeshedIntrinsicFrom};
pub fn is_transmutable<Src, Dst>()
where
Dst: BikeshedIntrinsicFrom<Src>,
{
}
}
#[repr(C)]
struct Zst;
enum V0 {
B(!),
}
enum V2 {
V = 2,
}
enum Lopsided {
Smol(Zst),
Lorg(V0),
}
#[repr(C)]
#[repr(C)]
struct Dst(Lopsided, V2);
fn should_pad_variants() {
assert::is_transmutable::<Src, Dst>();
}

View file

@ -1,12 +0,0 @@
# ignore-cross-compile
include ../tools.mk
# ignore-windows
# `ln` is actually `cp` on msys.
all:
$(RUSTC) foo.rs
mkdir -p $(TMPDIR)/other
ln -nsf $(TMPDIR)/libfoo.rlib $(TMPDIR)/other
$(RUSTC) bar.rs -L $(TMPDIR)
$(RUSTC) baz.rs --extern foo=$(TMPDIR)/other/libfoo.rlib -L $(TMPDIR)

View file

@ -0,0 +1,21 @@
// Crates that are resolved normally have their path canonicalized and all
// symlinks resolved. This did not happen for paths specified
// using the --extern option to rustc, which could lead to rustc thinking
// that it encountered two different versions of a crate, when it's
// actually the same version found through different paths.
// See https://github.com/rust-lang/rust/pull/16505
// This test checks that --extern and symlinks together
// can result in successful compilation.
//@ ignore-cross-compile
use run_make_support::{create_symlink, cwd, fs_wrapper, rustc};
fn main() {
rustc().input("foo.rs").run();
fs_wrapper::create_dir_all("other");
create_symlink("libfoo.rlib", "other");
rustc().input("bar.rs").library_search_path(cwd()).run();
rustc().input("baz.rs").extern_("foo", "other").library_search_path(cwd()).run();
}

View file

@ -1,11 +0,0 @@
# ignore-cross-compile
include ../tools.mk
# ignore-windows
# `ln` is actually `cp` on msys.
all:
$(RUSTC) foo.rs -C prefer-dynamic
mkdir -p $(TMPDIR)/other
ln -nsf $(TMPDIR)/$(call DYLIB_GLOB,foo) $(TMPDIR)/other
$(RUSTC) bar.rs -L $(TMPDIR)/other

View file

@ -0,0 +1,16 @@
// When a directory and a symlink simultaneously exist with the same name,
// setting that name as the library search path should not cause rustc
// to avoid looking in the symlink and cause an error. This test creates
// a directory and a symlink named "other", and places the library in the symlink.
// If it succeeds, the library was successfully found.
// See https://github.com/rust-lang/rust/issues/12459
//@ ignore-cross-compile
use run_make_support::{create_symlink, dynamic_lib_name, fs_wrapper, rustc};
fn main() {
rustc().input("foo.rs").arg("-Cprefer-dynamic").run();
fs_wrapper::create_dir_all("other");
create_symlink(dynamic_lib_name("foo"), "other");
rustc().input("bar.rs").library_search_path("other").run();
}

View file

@ -1,10 +0,0 @@
# ignore-cross-compile
include ../tools.mk
# ignore-windows
# `ln` is actually `cp` on msys.
all:
$(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo.xxx
ln -nsf $(TMPDIR)/foo.xxx $(TMPDIR)/libfoo.rlib
$(RUSTC) bar.rs -L $(TMPDIR)

View file

@ -0,0 +1,16 @@
// Rustc did not recognize libraries which were symlinked
// to files having extension other than .rlib. This was fixed
// in #32828. This test creates a symlink to "foo.xxx", which has
// an unusual file extension, and checks that rustc can successfully
// use it as an rlib library.
// See https://github.com/rust-lang/rust/pull/32828
//@ ignore-cross-compile
use run_make_support::{create_symlink, cwd, rustc};
fn main() {
rustc().input("foo.rs").crate_type("rlib").output("foo.xxx").run();
create_symlink("foo.xxx", "libfoo.rlib");
rustc().input("bar.rs").library_search_path(cwd()).run();
}

View file

@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied
--> $DIR/typeck-default-trait-impl-precedence.rs:19:20 --> $DIR/typeck-default-trait-impl-precedence.rs:19:20
| |
LL | is_defaulted::<&'static u32>(); LL | is_defaulted::<&'static u32>();
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted` | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted`
| |
note: required for `&'static u32` to implement `Defaulted` note: required for `&'static u32` to implement `Defaulted`
--> $DIR/typeck-default-trait-impl-precedence.rs:10:19 --> $DIR/typeck-default-trait-impl-precedence.rs:10:19

View file

@ -1,8 +1,8 @@
error[E0284]: type annotations needed: cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T` error[E0284]: type annotations needed: cannot normalize `<dyn Object<U, Output = T> as Object<U>>::Output`
--> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:41 --> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:41
| |
LL | foo::<dyn Object<U, Output = T>, U>(x) LL | foo::<dyn Object<U, Output = T>, U>(x)
| ^ cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T` | ^ cannot normalize `<dyn Object<U, Output = T> as Object<U>>::Output`
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -23,7 +23,7 @@ fn foo<T: ?Sized, U>(x: <T as Object<U>>::Output) -> U {
#[allow(dead_code)] #[allow(dead_code)]
fn transmute<T, U>(x: T) -> U { fn transmute<T, U>(x: T) -> U {
foo::<dyn Object<U, Output = T>, U>(x) foo::<dyn Object<U, Output = T>, U>(x)
//[next]~^ ERROR type annotations needed: cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T` //[next]~^ ERROR type annotations needed: cannot normalize `<dyn Object<U, Output = T> as Object<U>>::Output`
} }
fn main() {} fn main() {}

View file

@ -16,11 +16,11 @@ LL | | for<'a> *const T: ToUnit<'a>,
| |
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
error[E0284]: type annotations needed: cannot satisfy `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc == usize` error[E0284]: type annotations needed: cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`
--> $DIR/associated-type.rs:44:59 --> $DIR/associated-type.rs:44:59
| |
LL | foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); LL | foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
| ^^^^^^ cannot satisfy `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc == usize` | ^^^^^^ cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -42,5 +42,5 @@ fn foo<T: Overlap<U>, U>(x: T::Assoc) -> T::Assoc {
fn main() { fn main() {
foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
//[next]~^ ERROR: cannot satisfy //[next]~^ ERROR: cannot normalize
} }

View file

@ -25,7 +25,7 @@ LL | SelectInt.check("bar");
= help: the trait `AsExpression<Text>` is implemented for `&str` = help: the trait `AsExpression<Text>` is implemented for `&str`
= help: for that trait implementation, expected `Text`, found `Integer` = help: for that trait implementation, expected `Text`, found `Integer`
error[E0271]: type mismatch resolving `<&str as AsExpression<<SelectInt as Expression>::SqlType>>::Expression == _` error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
--> $DIR/as_expression.rs:57:5 --> $DIR/as_expression.rs:57:5
| |
LL | SelectInt.check("bar"); LL | SelectInt.check("bar");

View file

@ -2,7 +2,7 @@ error[E0277]: the trait bound `i32: Baz<Self>` is not satisfied
--> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30 --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30
| |
LL | type Bar<T>: Baz<Self> = i32; LL | type Bar<T>: Baz<Self> = i32;
| ^^^ the trait `Eq<i32>` is not implemented for `i32`, which is required by `i32: Baz<Self>` | ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`, which is required by `i32: Baz<Self>`
| |
note: required for `i32` to implement `Baz<Self>` note: required for `i32` to implement `Baz<Self>`
--> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23 --> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23

View file

@ -1,8 +1,8 @@
error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: <T as Trait<'_>>::Assoc` error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to <T as Trait<'_>>::Assoc`
--> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50 --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50
| |
LL | let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::<T>(); LL | let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::<T>();
| ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: <T as Trait<'_>>::Assoc` | ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to <T as Trait<'_>>::Assoc`
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -0,0 +1,28 @@
#![feature(impl_trait_in_assoc_type)]
trait Foo: Sized {
type Bar;
type Gat<T: Foo>;
fn foo(self) -> (<Self as Foo>::Gat<u32>, <Self as Foo>::Gat<Self>);
}
impl Foo for u32 {
type Bar = ();
type Gat<T: Foo> = ();
fn foo(self) -> (<Self as Foo>::Gat<u32>, <Self as Foo>::Gat<Self>) {
((), ())
}
}
impl Foo for () {
type Bar = impl Sized;
type Gat<T: Foo> = <T as Foo>::Bar;
// Because we encounter `Gat<u32>` first, we never walk into another `Gat`
// again, thus missing the opaque type that we could be defining.
fn foo(self) -> (<Self as Foo>::Gat<u32>, <Self as Foo>::Gat<Self>) {
((), ())
//~^ ERROR: mismatched types
}
}
fn main() {}

View file

@ -0,0 +1,20 @@
error[E0308]: mismatched types
--> $DIR/associated-type-undefine.rs:23:14
|
LL | type Bar = impl Sized;
| ---------- the expected opaque type
...
LL | ((), ())
| ^^ expected opaque type, found `()`
|
= note: expected opaque type `<() as Foo>::Bar`
found unit type `()`
note: this item must have the opaque type in its signature in order to be able to register hidden types
--> $DIR/associated-type-undefine.rs:22:8
|
LL | fn foo(self) -> (<Self as Foo>::Gat<u32>, <Self as Foo>::Gat<Self>) {
| ^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -46,7 +46,7 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
--> $DIR/nested_impl_trait.rs:6:46 --> $DIR/nested_impl_trait.rs:6:46
| |
LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x } LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>` | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
| |
= help: the trait `Into<U>` is implemented for `T` = help: the trait `Into<U>` is implemented for `T`
= note: required for `impl Into<u32>` to implement `Into<impl Debug>` = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
@ -55,7 +55,7 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
--> $DIR/nested_impl_trait.rs:19:34 --> $DIR/nested_impl_trait.rs:19:34
| |
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x } LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>` | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
| |
= help: the trait `Into<U>` is implemented for `T` = help: the trait `Into<U>` is implemented for `T`
= note: required for `impl Into<u32>` to implement `Into<impl Debug>` = note: required for `impl Into<u32>` to implement `Into<impl Debug>`

View file

@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
LL | assert_send::<&'static (dyn Dummy + 'static)>(); LL | assert_send::<&'static (dyn Dummy + 'static)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
| |
= help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
note: required by a bound in `assert_send` note: required by a bound in `assert_send`
--> $DIR/kindck-send-object.rs:5:18 --> $DIR/kindck-send-object.rs:5:18

View file

@ -4,7 +4,7 @@ error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
LL | assert_send::<&'a dyn Dummy>(); LL | assert_send::<&'a dyn Dummy>();
| ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely | ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
| |
= help: the trait `Sync` is not implemented for `&'a (dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
= note: required for `&'a (dyn Dummy + 'a)` to implement `Send` = note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
note: required by a bound in `assert_send` note: required by a bound in `assert_send`
--> $DIR/kindck-send-object1.rs:5:18 --> $DIR/kindck-send-object1.rs:5:18

View file

@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
LL | assert_send::<&'static dyn Dummy>(); LL | assert_send::<&'static dyn Dummy>();
| ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
| |
= help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
note: required by a bound in `assert_send` note: required by a bound in `assert_send`
--> $DIR/kindck-send-object2.rs:3:18 --> $DIR/kindck-send-object2.rs:3:18

View file

@ -4,7 +4,7 @@ error[E0277]: `&mut &mut &mut &mut Vec<i32>` is not an iterator
LL | for _ in &mut &mut v {} LL | for _ in &mut &mut v {}
| ^^^^^^^^^^^ `&mut &mut &mut &mut Vec<i32>` is not an iterator | ^^^^^^^^^^^ `&mut &mut &mut &mut Vec<i32>` is not an iterator
| |
= help: the trait `Iterator` is not implemented for `&mut &mut &mut &mut Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator` = help: the trait `Iterator` is not implemented for `Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator`
= note: required for `&mut Vec<i32>` to implement `Iterator` = note: required for `&mut Vec<i32>` to implement `Iterator`
= note: 3 redundant requirements hidden = note: 3 redundant requirements hidden
= note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator` = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
@ -21,7 +21,7 @@ error[E0277]: `&mut &mut &mut [u8; 1]` is not an iterator
LL | for _ in &mut v {} LL | for _ in &mut v {}
| ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator | ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator
| |
= help: the trait `Iterator` is not implemented for `&mut &mut &mut [u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator`
= note: required for `&mut [u8; 1]` to implement `Iterator` = note: required for `&mut [u8; 1]` to implement `Iterator`
= note: 2 redundant requirements hidden = note: 2 redundant requirements hidden
= note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator` = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`

View file

@ -18,3 +18,4 @@ fn weird1() -> impl !Sized + Sized {}
//~^ ERROR type mismatch resolving `impl !Sized + Sized == ()` //~^ ERROR type mismatch resolving `impl !Sized + Sized == ()`
fn weird2() -> impl !Sized {} fn weird2() -> impl !Sized {}
//~^ ERROR type mismatch resolving `impl !Sized == ()` //~^ ERROR type mismatch resolving `impl !Sized == ()`
//~| ERROR the size for values of type `impl !Sized` cannot be known at compilation time

View file

@ -16,6 +16,15 @@ error[E0271]: type mismatch resolving `impl !Sized == ()`
LL | fn weird2() -> impl !Sized {} LL | fn weird2() -> impl !Sized {}
| ^^^^^^^^^^^ types differ | ^^^^^^^^^^^ types differ
error[E0277]: the size for values of type `impl !Sized` cannot be known at compilation time
--> $DIR/opaque-type-unsatisfied-bound.rs:19:16
|
LL | fn weird2() -> impl !Sized {}
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `impl !Sized`
= note: the return type of a function must have a statically known size
error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied
--> $DIR/opaque-type-unsatisfied-bound.rs:12:13 --> $DIR/opaque-type-unsatisfied-bound.rs:12:13
| |
@ -30,7 +39,7 @@ note: required by a bound in `consume`
LL | fn consume(_: impl Trait) {} LL | fn consume(_: impl Trait) {}
| ^^^^^ required by this bound in `consume` | ^^^^^ required by this bound in `consume`
error: aborting due to 4 previous errors error: aborting due to 5 previous errors
Some errors have detailed explanations: E0271, E0277. Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`. For more information about an error, try `rustc --explain E0271`.

View file

@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
LL | is_send(foo()); LL | is_send(foo());
| ^^^^^ future returned by `foo` is not `Send` | ^^^^^ future returned by `foo` is not `Send`
| |
= help: the trait `Sync` is not implemented for `impl Future<Output = ()>`, which is required by `impl Future<Output = ()>: Send` = help: the trait `Sync` is not implemented for `NotSync`, which is required by `impl Future<Output = ()>: Send`
note: future is not `Send` as this value is used across an await note: future is not `Send` as this value is used across an await
--> $DIR/auto-with-drop_tracking_mir.rs:16:11 --> $DIR/auto-with-drop_tracking_mir.rs:16:11
| |

View file

@ -1,8 +1,8 @@
error[E0284]: type annotations needed: cannot satisfy `{ || {} } == _` error[E0284]: type annotations needed: cannot normalize `X::{constant#0}`
--> $DIR/const-region-infer-to-static-in-binder.rs:4:10 --> $DIR/const-region-infer-to-static-in-binder.rs:4:10
| |
LL | struct X<const FN: fn() = { || {} }>; LL | struct X<const FN: fn() = { || {} }>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `{ || {} } == _` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}`
error: using function pointers as const generic parameters is forbidden error: using function pointers as const generic parameters is forbidden
--> $DIR/const-region-infer-to-static-in-binder.rs:4:20 --> $DIR/const-region-infer-to-static-in-binder.rs:4:20

View file

@ -4,6 +4,11 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
LL | needs_foo::<()>(); LL | needs_foo::<()>();
| ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo` | ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo`
| |
help: this trait has no implementations, consider adding one
--> $DIR/point-at-failing-nested.rs:4:1
|
LL | trait Bar {}
| ^^^^^^^^^
note: required for `()` to implement `Foo` note: required for `()` to implement `Foo`
--> $DIR/point-at-failing-nested.rs:9:12 --> $DIR/point-at-failing-nested.rs:9:12
| |

View file

@ -0,0 +1,17 @@
//@ compile-flags: -Znext-solver
trait Trait {
type Assoc;
}
fn test_poly<T>() {
let x: <T as Trait>::Assoc = ();
//~^ ERROR the trait bound `T: Trait` is not satisfied
}
fn test() {
let x: <i32 as Trait>::Assoc = ();
//~^ ERROR the trait bound `i32: Trait` is not satisfied
}
fn main() {}

View file

@ -0,0 +1,26 @@
error[E0277]: the trait bound `T: Trait` is not satisfied
--> $DIR/projection-trait-ref.rs:8:12
|
LL | let x: <T as Trait>::Assoc = ();
| ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
LL | fn test_poly<T: Trait>() {
| +++++++
error[E0277]: the trait bound `i32: Trait` is not satisfied
--> $DIR/projection-trait-ref.rs:13:12
|
LL | let x: <i32 as Trait>::Assoc = ();
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `i32`
|
help: this trait has no implementations, consider adding one
--> $DIR/projection-trait-ref.rs:3:1
|
LL | trait Trait {
| ^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -6,6 +6,11 @@ LL | needs_foo(());
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
help: this trait has no implementations, consider adding one
--> $DIR/where-clause-doesnt-apply.rs:2:1
|
LL | trait Bar {}
| ^^^^^^^^^
note: required for `()` to implement `Foo` note: required for `()` to implement `Foo`
--> $DIR/where-clause-doesnt-apply.rs:4:9 --> $DIR/where-clause-doesnt-apply.rs:4:9
| |

View file

@ -2,13 +2,8 @@ error[E0271]: type mismatch resolving `<T as Foo>::Assoc == i32`
--> $DIR/param-candidate-shadows-project.rs:27:19 --> $DIR/param-candidate-shadows-project.rs:27:19
| |
LL | require_bar::<T>(); LL | require_bar::<T>();
| ^ type mismatch resolving `<T as Foo>::Assoc == i32` | ^ types differ
| |
note: types differ
--> $DIR/param-candidate-shadows-project.rs:10:18
|
LL | type Assoc = i32;
| ^^^
note: required for `T` to implement `Bar` note: required for `T` to implement `Bar`
--> $DIR/param-candidate-shadows-project.rs:13:9 --> $DIR/param-candidate-shadows-project.rs:13:9
| |

View file

@ -24,7 +24,7 @@ fn needs_bar<T: Bar>() {}
fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() { fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() {
needs_bar::<T>(); needs_bar::<T>();
//~^ ERROR type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32` //~^ ERROR type annotations needed: cannot normalize
} }
fn main() {} fn main() {}

View file

@ -1,8 +1,8 @@
error[E0284]: type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32` error[E0284]: type annotations needed: cannot normalize `<T as Foo>::Assoc`
--> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17 --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17
| |
LL | needs_bar::<T>(); LL | needs_bar::<T>();
| ^ cannot satisfy `<T as Foo>::Assoc == i32` | ^ cannot normalize `<T as Foo>::Assoc`
| |
note: required for `T` to implement `Bar` note: required for `T` to implement `Bar`
--> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9 --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9

View file

@ -10,23 +10,23 @@ LL | #![feature(specialization)]
error: cannot normalize `<T as Default>::Id: '_` error: cannot normalize `<T as Default>::Id: '_`
error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id == _` error[E0284]: type annotations needed: cannot normalize `<T as Default>::Id`
--> $DIR/specialization-transmute.rs:15:23 --> $DIR/specialization-transmute.rs:15:23
| |
LL | fn intu(&self) -> &Self::Id { LL | fn intu(&self) -> &Self::Id {
| ^^^^^^^^^ cannot satisfy `<T as Default>::Id == _` | ^^^^^^^^^ cannot normalize `<T as Default>::Id`
error[E0284]: type annotations needed: cannot satisfy `T <: <T as Default>::Id` error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to T`
--> $DIR/specialization-transmute.rs:17:9 --> $DIR/specialization-transmute.rs:17:9
| |
LL | self LL | self
| ^^^^ cannot satisfy `T <: <T as Default>::Id` | ^^^^ cannot satisfy `<T as Default>::Id normalizes-to T`
error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id == Option<NonZero<u8>>` error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
--> $DIR/specialization-transmute.rs:28:13 --> $DIR/specialization-transmute.rs:28:13
| |
LL | let s = transmute::<u8, Option<NonZero<u8>>>(0); LL | let s = transmute::<u8, Option<NonZero<u8>>>(0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id == Option<NonZero<u8>>` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
| |
note: required by a bound in `transmute` note: required by a bound in `transmute`
--> $DIR/specialization-transmute.rs:21:25 --> $DIR/specialization-transmute.rs:21:25

View file

@ -18,5 +18,5 @@ fn test<T: Default<Id = U>, U>() {}
fn main() { fn main() {
test::<u32, ()>(); test::<u32, ()>();
//~^ ERROR cannot satisfy `<u32 as Default>::Id == ()` //~^ ERROR cannot satisfy `<u32 as Default>::Id normalizes-to ()`
} }

View file

@ -8,11 +8,11 @@ LL | #![feature(specialization)]
= help: consider using `min_specialization` instead, which is more stable and complete = help: consider using `min_specialization` instead, which is more stable and complete
= note: `#[warn(incomplete_features)]` on by default = note: `#[warn(incomplete_features)]` on by default
error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id == ()` error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id normalizes-to ()`
--> $DIR/specialization-unconstrained.rs:20:5 --> $DIR/specialization-unconstrained.rs:20:5
| |
LL | test::<u32, ()>(); LL | test::<u32, ()>();
| ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id == ()` | ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id normalizes-to ()`
| |
note: required by a bound in `test` note: required by a bound in `test`
--> $DIR/specialization-unconstrained.rs:17:20 --> $DIR/specialization-unconstrained.rs:17:20

View file

@ -2,7 +2,7 @@ error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
--> $DIR/root-obligation.rs:6:38 --> $DIR/root-obligation.rs:6:38
| |
LL | .filter(|c| "aeiou".contains(c)) LL | .filter(|c| "aeiou".contains(c))
| -------- ^ the trait `Fn(char)` is not implemented for `&char`, which is required by `&char: Pattern<'_>` | -------- ^ the trait `Fn(char)` is not implemented for `char`, which is required by `&char: Pattern<'_>`
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |

View file

@ -0,0 +1,26 @@
//@ check-pass
//! Tests that we do not regress rust-lang/rust#125811
#![feature(transmutability)]
fn assert_transmutable<T>()
where
(): std::mem::BikeshedIntrinsicFrom<T>
{}
enum Uninhabited {}
enum SingleInhabited {
X,
Y(Uninhabited)
}
enum SingleUninhabited {
X(Uninhabited),
Y(Uninhabited),
}
fn main() {
assert_transmutable::<Uninhabited>();
assert_transmutable::<SingleInhabited>();
assert_transmutable::<SingleUninhabited>();
}

View file

@ -2,7 +2,7 @@ error[E0277]: `&u8` cannot be safely transmuted into `&UnsafeCell<u8>`
--> $DIR/unsafecell.rs:27:50 --> $DIR/unsafecell.rs:27:50
| |
LL | assert::is_maybe_transmutable::<&'static u8, &'static UnsafeCell<u8>>(); LL | assert::is_maybe_transmutable::<&'static u8, &'static UnsafeCell<u8>>();
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell<u8>` | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell<u8>`
| |
note: required by a bound in `is_maybe_transmutable` note: required by a bound in `is_maybe_transmutable`
--> $DIR/unsafecell.rs:12:14 --> $DIR/unsafecell.rs:12:14
@ -17,7 +17,7 @@ error[E0277]: `&UnsafeCell<u8>` cannot be safely transmuted into `&UnsafeCell<u8
--> $DIR/unsafecell.rs:29:62 --> $DIR/unsafecell.rs:29:62
| |
LL | assert::is_maybe_transmutable::<&'static UnsafeCell<u8>, &'static UnsafeCell<u8>>(); LL | assert::is_maybe_transmutable::<&'static UnsafeCell<u8>, &'static UnsafeCell<u8>>();
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell<u8>` | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell<u8>`
| |
note: required by a bound in `is_maybe_transmutable` note: required by a bound in `is_maybe_transmutable`
--> $DIR/unsafecell.rs:12:14 --> $DIR/unsafecell.rs:12:14

View file

@ -1,4 +1,4 @@
error[E0284]: type annotations needed: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()` error[E0284]: type annotations needed: cannot satisfy `Bar == _`
--> $DIR/issue-84660-unsoundness.rs:22:37 --> $DIR/issue-84660-unsoundness.rs:22:37
| |
LL | fn convert(_i: In) -> Self::Out { LL | fn convert(_i: In) -> Self::Out {
@ -7,7 +7,7 @@ LL | |
LL | | LL | |
LL | | unreachable!(); LL | | unreachable!();
LL | | } LL | | }
| |_____^ cannot satisfy `<Out as Trait<Bar, In>>::Out == ()` | |_____^ cannot satisfy `Bar == _`
error[E0119]: conflicting implementations of trait `Trait<Bar, _>` error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
--> $DIR/issue-84660-unsoundness.rs:29:1 --> $DIR/issue-84660-unsoundness.rs:29:1

View file

@ -20,7 +20,7 @@ trait Trait<T, In> {
impl<In, Out> Trait<Bar, In> for Out { impl<In, Out> Trait<Bar, In> for Out {
type Out = Out; type Out = Out;
fn convert(_i: In) -> Self::Out { fn convert(_i: In) -> Self::Out {
//[next]~^ ERROR: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()` //[next]~^ ERROR: cannot satisfy `Bar == _`
//[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`, but has it in its signature //[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`, but has it in its signature
unreachable!(); unreachable!();
} }

View file

@ -0,0 +1,16 @@
trait Foo<'s> {}
impl<'s> Foo<'s> for () {}
struct Bar;
impl<'s, T: Foo<'s>> From<T> for Bar {
fn from(_: T) -> Self {
Bar
}
}
fn main() {
let _: Bar = ((),).into();
//~^ ERROR he trait bound `((),): Into<Bar>` is not satisfied
}

View file

@ -0,0 +1,20 @@
error[E0277]: the trait bound `((),): Into<Bar>` is not satisfied
--> $DIR/suggest-similar-impls-for-root-obligation.rs:14:24
|
LL | let _: Bar = ((),).into();
| ^^^^ the trait `Foo<'_>` is not implemented for `((),)`, which is required by `((),): Into<_>`
|
= help: the trait `Foo<'_>` is implemented for `()`
= help: for that trait implementation, expected `()`, found `((),)`
note: required for `Bar` to implement `From<((),)>`
--> $DIR/suggest-similar-impls-for-root-obligation.rs:7:22
|
LL | impl<'s, T: Foo<'s>> From<T> for Bar {
| ------- ^^^^^^^ ^^^
| |
| unsatisfied trait bound introduced here
= note: required for `((),)` to implement `Into<Bar>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.