Auto merge of #122900 - matthiaskrgr:rollup-nls90mb, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #114009 (compiler: allow transmute of ZST arrays with generics) - #122195 (Note that the caller chooses a type for type param) - #122651 (Suggest `_` for missing generic arguments in turbofish) - #122784 (Add `tag_for_variant` query) - #122839 (Split out `PredicatePolarity` from `ImplPolarity`) - #122873 (Merge my contributor emails into one using mailmap) - #122885 (Adjust better spastorino membership to triagebot's adhoc_groups) - #122888 (add a couple more tests) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0ad5e0d2de
72 changed files with 777 additions and 425 deletions
1
.mailmap
1
.mailmap
|
@ -259,6 +259,7 @@ James Hinshelwood <jameshinshelwood1@gmail.com> <james.hinshelwood@bigpayme.com>
|
||||||
James Miller <bladeon@gmail.com> <james@aatch.net>
|
James Miller <bladeon@gmail.com> <james@aatch.net>
|
||||||
James Perry <james.austin.perry@gmail.com>
|
James Perry <james.austin.perry@gmail.com>
|
||||||
James Sanderson <zofrex@gmail.com>
|
James Sanderson <zofrex@gmail.com>
|
||||||
|
Jan-Erik Rediger <janerik@fnordig.de> <badboy@archlinux.us>
|
||||||
Jaro Fietz <jaro.fietz@gmx.de>
|
Jaro Fietz <jaro.fietz@gmx.de>
|
||||||
Jason Fager <jfager@gmail.com>
|
Jason Fager <jfager@gmail.com>
|
||||||
Jason Liquorish <jason@liquori.sh> <Bassetts@users.noreply.github.com>
|
Jason Liquorish <jason@liquori.sh> <Bassetts@users.noreply.github.com>
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
self.prove_predicate(
|
self.prove_predicate(
|
||||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Trait(
|
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Trait(
|
||||||
ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive },
|
ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Positive },
|
||||||
))),
|
))),
|
||||||
locations,
|
locations,
|
||||||
category,
|
category,
|
||||||
|
|
193
compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
Normal file
193
compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
use crate::interpret::{self, HasStaticRootDefId, ImmTy, Immediate, InterpCx, PointerArithmetic};
|
||||||
|
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult};
|
||||||
|
use rustc_middle::mir::*;
|
||||||
|
use rustc_middle::query::TyCtxtAt;
|
||||||
|
use rustc_middle::ty;
|
||||||
|
use rustc_middle::ty::layout::TyAndLayout;
|
||||||
|
use rustc_span::def_id::DefId;
|
||||||
|
|
||||||
|
/// Macro for machine-specific `InterpError` without allocation.
|
||||||
|
/// (These will never be shown to the user, but they help diagnose ICEs.)
|
||||||
|
pub macro throw_machine_stop_str($($tt:tt)*) {{
|
||||||
|
// We make a new local type for it. The type itself does not carry any information,
|
||||||
|
// but its vtable (for the `MachineStopType` trait) does.
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Zst;
|
||||||
|
// Printing this type shows the desired string.
|
||||||
|
impl std::fmt::Display for Zst {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, $($tt)*)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl rustc_middle::mir::interpret::MachineStopType for Zst {
|
||||||
|
fn diagnostic_message(&self) -> rustc_errors::DiagMessage {
|
||||||
|
self.to_string().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_args(
|
||||||
|
self: Box<Self>,
|
||||||
|
_: &mut dyn FnMut(rustc_errors::DiagArgName, rustc_errors::DiagArgValue),
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
throw_machine_stop!(Zst)
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub struct DummyMachine;
|
||||||
|
|
||||||
|
impl HasStaticRootDefId for DummyMachine {
|
||||||
|
fn static_def_id(&self) -> Option<rustc_hir::def_id::LocalDefId> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
|
||||||
|
interpret::compile_time_machine!(<'mir, 'tcx>);
|
||||||
|
type MemoryKind = !;
|
||||||
|
const PANIC_ON_ALLOC_FAIL: bool = true;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||||
|
false // no reason to enforce alignment
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn before_access_global(
|
||||||
|
_tcx: TyCtxtAt<'tcx>,
|
||||||
|
_machine: &Self,
|
||||||
|
_alloc_id: AllocId,
|
||||||
|
alloc: ConstAllocation<'tcx>,
|
||||||
|
_static_def_id: Option<DefId>,
|
||||||
|
is_write: bool,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
|
if is_write {
|
||||||
|
throw_machine_stop_str!("can't write to global");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the static allocation is mutable, then we can't const prop it as its content
|
||||||
|
// might be different at runtime.
|
||||||
|
if alloc.inner().mutability.is_mut() {
|
||||||
|
throw_machine_stop_str!("can't access mutable globals in ConstProp");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_mir_or_eval_fn(
|
||||||
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
|
_instance: ty::Instance<'tcx>,
|
||||||
|
_abi: rustc_target::spec::abi::Abi,
|
||||||
|
_args: &[interpret::FnArg<'tcx, Self::Provenance>],
|
||||||
|
_destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
|
||||||
|
_target: Option<BasicBlock>,
|
||||||
|
_unwind: UnwindAction,
|
||||||
|
) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn panic_nounwind(
|
||||||
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
|
_msg: &str,
|
||||||
|
) -> interpret::InterpResult<'tcx> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_intrinsic(
|
||||||
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
|
_instance: ty::Instance<'tcx>,
|
||||||
|
_args: &[interpret::OpTy<'tcx, Self::Provenance>],
|
||||||
|
_destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
|
||||||
|
_target: Option<BasicBlock>,
|
||||||
|
_unwind: UnwindAction,
|
||||||
|
) -> interpret::InterpResult<'tcx> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_panic(
|
||||||
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
|
_msg: &rustc_middle::mir::AssertMessage<'tcx>,
|
||||||
|
_unwind: UnwindAction,
|
||||||
|
) -> interpret::InterpResult<'tcx> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn binary_ptr_op(
|
||||||
|
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||||
|
bin_op: BinOp,
|
||||||
|
left: &interpret::ImmTy<'tcx, Self::Provenance>,
|
||||||
|
right: &interpret::ImmTy<'tcx, Self::Provenance>,
|
||||||
|
) -> interpret::InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)> {
|
||||||
|
use rustc_middle::mir::BinOp::*;
|
||||||
|
Ok(match bin_op {
|
||||||
|
Eq | Ne | Lt | Le | Gt | Ge => {
|
||||||
|
// Types can differ, e.g. fn ptrs with different `for`.
|
||||||
|
assert_eq!(left.layout.abi, right.layout.abi);
|
||||||
|
let size = ecx.pointer_size();
|
||||||
|
// Just compare the bits. ScalarPairs are compared lexicographically.
|
||||||
|
// We thus always compare pairs and simply fill scalars up with 0.
|
||||||
|
// If the pointer has provenance, `to_bits` will return `Err` and we bail out.
|
||||||
|
let left = match **left {
|
||||||
|
Immediate::Scalar(l) => (l.to_bits(size)?, 0),
|
||||||
|
Immediate::ScalarPair(l1, l2) => (l1.to_bits(size)?, l2.to_bits(size)?),
|
||||||
|
Immediate::Uninit => panic!("we should never see uninit data here"),
|
||||||
|
};
|
||||||
|
let right = match **right {
|
||||||
|
Immediate::Scalar(r) => (r.to_bits(size)?, 0),
|
||||||
|
Immediate::ScalarPair(r1, r2) => (r1.to_bits(size)?, r2.to_bits(size)?),
|
||||||
|
Immediate::Uninit => panic!("we should never see uninit data here"),
|
||||||
|
};
|
||||||
|
let res = match bin_op {
|
||||||
|
Eq => left == right,
|
||||||
|
Ne => left != right,
|
||||||
|
Lt => left < right,
|
||||||
|
Le => left <= right,
|
||||||
|
Gt => left > right,
|
||||||
|
Ge => left >= right,
|
||||||
|
_ => bug!(),
|
||||||
|
};
|
||||||
|
(ImmTy::from_bool(res, *ecx.tcx), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some more operations are possible with atomics.
|
||||||
|
// The return value always has the provenance of the *left* operand.
|
||||||
|
Add | Sub | BitOr | BitAnd | BitXor => {
|
||||||
|
throw_machine_stop_str!("pointer arithmetic is not handled")
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => span_bug!(ecx.cur_span(), "Invalid operator on pointers: {:?}", bin_op),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expose_ptr(
|
||||||
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
|
_ptr: interpret::Pointer<Self::Provenance>,
|
||||||
|
) -> interpret::InterpResult<'tcx> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_frame_extra(
|
||||||
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
|
_frame: interpret::Frame<'mir, 'tcx, Self::Provenance>,
|
||||||
|
) -> interpret::InterpResult<
|
||||||
|
'tcx,
|
||||||
|
interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
|
||||||
|
> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stack<'a>(
|
||||||
|
_ecx: &'a InterpCx<'mir, 'tcx, Self>,
|
||||||
|
) -> &'a [interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
|
||||||
|
// Return an empty stack instead of panicking, as `cur_span` uses it to evaluate constants.
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stack_mut<'a>(
|
||||||
|
_ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
|
||||||
|
) -> &'a mut Vec<interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ use either::{Left, Right};
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
|
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
|
||||||
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
|
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
|
||||||
use rustc_middle::query::TyCtxtAt;
|
use rustc_middle::query::{Key, TyCtxtAt};
|
||||||
use rustc_middle::traits::Reveal;
|
use rustc_middle::traits::Reveal;
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
|
@ -243,6 +243,24 @@ pub(crate) fn turn_into_const_value<'tcx>(
|
||||||
op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false)
|
op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes the tag (if any) for a given type and variant.
|
||||||
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
|
pub fn tag_for_variant_provider<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
(ty, variant_index): (Ty<'tcx>, abi::VariantIdx),
|
||||||
|
) -> Option<ty::ScalarInt> {
|
||||||
|
assert!(ty.is_enum());
|
||||||
|
|
||||||
|
let ecx = InterpCx::new(
|
||||||
|
tcx,
|
||||||
|
ty.default_span(tcx),
|
||||||
|
ty::ParamEnv::reveal_all(),
|
||||||
|
crate::const_eval::DummyMachine,
|
||||||
|
);
|
||||||
|
|
||||||
|
ecx.tag_for_variant(ty, variant_index).unwrap().map(|(tag, _tag_field)| tag)
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
pub fn eval_to_const_value_raw_provider<'tcx>(
|
pub fn eval_to_const_value_raw_provider<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
|
|
@ -7,12 +7,14 @@ use rustc_middle::ty::{self, Ty};
|
||||||
|
|
||||||
use crate::interpret::format_interp_error;
|
use crate::interpret::format_interp_error;
|
||||||
|
|
||||||
|
mod dummy_machine;
|
||||||
mod error;
|
mod error;
|
||||||
mod eval_queries;
|
mod eval_queries;
|
||||||
mod fn_queries;
|
mod fn_queries;
|
||||||
mod machine;
|
mod machine;
|
||||||
mod valtrees;
|
mod valtrees;
|
||||||
|
|
||||||
|
pub use dummy_machine::*;
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
pub use eval_queries::*;
|
pub use eval_queries::*;
|
||||||
pub use fn_queries::*;
|
pub use fn_queries::*;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
|
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, ScalarInt, Ty};
|
||||||
use rustc_target::abi::{self, TagEncoding};
|
use rustc_target::abi::{self, TagEncoding};
|
||||||
use rustc_target::abi::{VariantIdx, Variants};
|
use rustc_target::abi::{VariantIdx, Variants};
|
||||||
|
|
||||||
|
@ -28,78 +28,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
throw_ub!(UninhabitedEnumVariantWritten(variant_index))
|
throw_ub!(UninhabitedEnumVariantWritten(variant_index))
|
||||||
}
|
}
|
||||||
|
|
||||||
match dest.layout().variants {
|
match self.tag_for_variant(dest.layout().ty, variant_index)? {
|
||||||
abi::Variants::Single { index } => {
|
Some((tag, tag_field)) => {
|
||||||
assert_eq!(index, variant_index);
|
|
||||||
}
|
|
||||||
abi::Variants::Multiple {
|
|
||||||
tag_encoding: TagEncoding::Direct,
|
|
||||||
tag: tag_layout,
|
|
||||||
tag_field,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
// No need to validate that the discriminant here because the
|
// No need to validate that the discriminant here because the
|
||||||
// `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
|
// `TyAndLayout::for_variant()` call earlier already checks the
|
||||||
|
// variant is valid.
|
||||||
let discr_val = dest
|
|
||||||
.layout()
|
|
||||||
.ty
|
|
||||||
.discriminant_for_variant(*self.tcx, variant_index)
|
|
||||||
.unwrap()
|
|
||||||
.val;
|
|
||||||
|
|
||||||
// raw discriminants for enums are isize or bigger during
|
|
||||||
// their computation, but the in-memory tag is the smallest possible
|
|
||||||
// representation
|
|
||||||
let size = tag_layout.size(self);
|
|
||||||
let tag_val = size.truncate(discr_val);
|
|
||||||
|
|
||||||
let tag_dest = self.project_field(dest, tag_field)?;
|
let tag_dest = self.project_field(dest, tag_field)?;
|
||||||
self.write_scalar(Scalar::from_uint(tag_val, size), &tag_dest)?;
|
self.write_scalar(tag, &tag_dest)
|
||||||
}
|
}
|
||||||
abi::Variants::Multiple {
|
None => {
|
||||||
tag_encoding:
|
// No need to write the tag here, because an untagged variant is
|
||||||
TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
|
// implicitly encoded. For `Niche`-optimized enums, it's by
|
||||||
tag: tag_layout,
|
// simply by having a value that is outside the niche variants.
|
||||||
tag_field,
|
// But what if the data stored here does not actually encode
|
||||||
..
|
// this variant? That would be bad! So let's double-check...
|
||||||
} => {
|
let actual_variant = self.read_discriminant(&dest.to_op(self)?)?;
|
||||||
// No need to validate that the discriminant here because the
|
if actual_variant != variant_index {
|
||||||
// `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
|
throw_ub!(InvalidNichedEnumVariantWritten { enum_ty: dest.layout().ty });
|
||||||
|
|
||||||
if variant_index != untagged_variant {
|
|
||||||
let variants_start = niche_variants.start().as_u32();
|
|
||||||
let variant_index_relative = variant_index
|
|
||||||
.as_u32()
|
|
||||||
.checked_sub(variants_start)
|
|
||||||
.expect("overflow computing relative variant idx");
|
|
||||||
// We need to use machine arithmetic when taking into account `niche_start`:
|
|
||||||
// tag_val = variant_index_relative + niche_start_val
|
|
||||||
let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;
|
|
||||||
let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
|
|
||||||
let variant_index_relative_val =
|
|
||||||
ImmTy::from_uint(variant_index_relative, tag_layout);
|
|
||||||
let tag_val = self.wrapping_binary_op(
|
|
||||||
mir::BinOp::Add,
|
|
||||||
&variant_index_relative_val,
|
|
||||||
&niche_start_val,
|
|
||||||
)?;
|
|
||||||
// Write result.
|
|
||||||
let niche_dest = self.project_field(dest, tag_field)?;
|
|
||||||
self.write_immediate(*tag_val, &niche_dest)?;
|
|
||||||
} else {
|
|
||||||
// The untagged variant is implicitly encoded simply by having a value that is
|
|
||||||
// outside the niche variants. But what if the data stored here does not
|
|
||||||
// actually encode this variant? That would be bad! So let's double-check...
|
|
||||||
let actual_variant = self.read_discriminant(&dest.to_op(self)?)?;
|
|
||||||
if actual_variant != variant_index {
|
|
||||||
throw_ub!(InvalidNichedEnumVariantWritten { enum_ty: dest.layout().ty });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read discriminant, return the runtime value as well as the variant index.
|
/// Read discriminant, return the runtime value as well as the variant index.
|
||||||
|
@ -277,4 +226,77 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
};
|
};
|
||||||
Ok(ImmTy::from_scalar(discr_value, discr_layout))
|
Ok(ImmTy::from_scalar(discr_value, discr_layout))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes the tag value and its field number (if any) of a given variant
|
||||||
|
/// of type `ty`.
|
||||||
|
pub(crate) fn tag_for_variant(
|
||||||
|
&self,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
variant_index: VariantIdx,
|
||||||
|
) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
|
||||||
|
match self.layout_of(ty)?.variants {
|
||||||
|
abi::Variants::Single { index } => {
|
||||||
|
assert_eq!(index, variant_index);
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
abi::Variants::Multiple {
|
||||||
|
tag_encoding: TagEncoding::Direct,
|
||||||
|
tag: tag_layout,
|
||||||
|
tag_field,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// raw discriminants for enums are isize or bigger during
|
||||||
|
// their computation, but the in-memory tag is the smallest possible
|
||||||
|
// representation
|
||||||
|
let discr = self.discriminant_for_variant(ty, variant_index)?;
|
||||||
|
let discr_size = discr.layout.size;
|
||||||
|
let discr_val = discr.to_scalar().to_bits(discr_size)?;
|
||||||
|
let tag_size = tag_layout.size(self);
|
||||||
|
let tag_val = tag_size.truncate(discr_val);
|
||||||
|
let tag = ScalarInt::try_from_uint(tag_val, tag_size).unwrap();
|
||||||
|
Ok(Some((tag, tag_field)))
|
||||||
|
}
|
||||||
|
|
||||||
|
abi::Variants::Multiple {
|
||||||
|
tag_encoding: TagEncoding::Niche { untagged_variant, .. },
|
||||||
|
..
|
||||||
|
} if untagged_variant == variant_index => {
|
||||||
|
// The untagged variant is implicitly encoded simply by having a
|
||||||
|
// value that is outside the niche variants.
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
abi::Variants::Multiple {
|
||||||
|
tag_encoding:
|
||||||
|
TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
|
||||||
|
tag: tag_layout,
|
||||||
|
tag_field,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
assert!(variant_index != untagged_variant);
|
||||||
|
let variants_start = niche_variants.start().as_u32();
|
||||||
|
let variant_index_relative = variant_index
|
||||||
|
.as_u32()
|
||||||
|
.checked_sub(variants_start)
|
||||||
|
.expect("overflow computing relative variant idx");
|
||||||
|
// We need to use machine arithmetic when taking into account `niche_start`:
|
||||||
|
// tag_val = variant_index_relative + niche_start_val
|
||||||
|
let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;
|
||||||
|
let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
|
||||||
|
let variant_index_relative_val =
|
||||||
|
ImmTy::from_uint(variant_index_relative, tag_layout);
|
||||||
|
let tag = self
|
||||||
|
.wrapping_binary_op(
|
||||||
|
mir::BinOp::Add,
|
||||||
|
&variant_index_relative_val,
|
||||||
|
&niche_start_val,
|
||||||
|
)?
|
||||||
|
.to_scalar()
|
||||||
|
.try_to_int()
|
||||||
|
.unwrap();
|
||||||
|
Ok(Some((tag, tag_field)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
const_eval::provide(providers);
|
const_eval::provide(providers);
|
||||||
|
providers.tag_for_variant = const_eval::tag_for_variant_provider;
|
||||||
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
|
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
|
||||||
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
|
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
|
||||||
providers.eval_static_initializer = const_eval::eval_static_initializer_provider;
|
providers.eval_static_initializer = const_eval::eval_static_initializer_provider;
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl<'tcx> Bounds<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
polarity: ty::ImplPolarity,
|
polarity: ty::PredicatePolarity,
|
||||||
) {
|
) {
|
||||||
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ impl<'tcx> Bounds<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
polarity: ty::ImplPolarity,
|
polarity: ty::PredicatePolarity,
|
||||||
) {
|
) {
|
||||||
self.clauses.push((
|
self.clauses.push((
|
||||||
trait_ref
|
trait_ref
|
||||||
|
|
|
@ -1322,7 +1322,7 @@ fn check_impl<'tcx>(
|
||||||
trait_ref,
|
trait_ref,
|
||||||
);
|
);
|
||||||
let trait_pred =
|
let trait_pred =
|
||||||
ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive };
|
ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Positive };
|
||||||
let mut obligations = traits::wf::trait_obligations(
|
let mut obligations = traits::wf::trait_obligations(
|
||||||
wfcx.infcx,
|
wfcx.infcx,
|
||||||
wfcx.param_env,
|
wfcx.param_env,
|
||||||
|
|
|
@ -554,7 +554,7 @@ fn infringing_fields_error(
|
||||||
}
|
}
|
||||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
|
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
|
||||||
trait_ref,
|
trait_ref,
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
..
|
..
|
||||||
})) = error_predicate.kind().skip_binder()
|
})) = error_predicate.kind().skip_binder()
|
||||||
{
|
{
|
||||||
|
|
|
@ -624,7 +624,7 @@ pub(super) fn implied_predicates_with_filter(
|
||||||
for &(pred, span) in implied_bounds {
|
for &(pred, span) in implied_bounds {
|
||||||
debug!("superbound: {:?}", pred);
|
debug!("superbound: {:?}", pred);
|
||||||
if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
|
if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
|
||||||
&& bound.polarity == ty::ImplPolarity::Positive
|
&& bound.polarity == ty::PredicatePolarity::Positive
|
||||||
{
|
{
|
||||||
tcx.at(span).super_predicates_of(bound.def_id());
|
tcx.at(span).super_predicates_of(bound.def_id());
|
||||||
}
|
}
|
||||||
|
@ -634,7 +634,7 @@ pub(super) fn implied_predicates_with_filter(
|
||||||
for &(pred, span) in implied_bounds {
|
for &(pred, span) in implied_bounds {
|
||||||
debug!("superbound: {:?}", pred);
|
debug!("superbound: {:?}", pred);
|
||||||
if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
|
if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
|
||||||
&& bound.polarity == ty::ImplPolarity::Positive
|
&& bound.polarity == ty::PredicatePolarity::Positive
|
||||||
{
|
{
|
||||||
tcx.at(span).implied_predicates_of(bound.def_id());
|
tcx.at(span).implied_predicates_of(bound.def_id());
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,16 +140,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
hir::GenericBound::Trait(poly_trait_ref, modifier) => {
|
hir::GenericBound::Trait(poly_trait_ref, modifier) => {
|
||||||
let (constness, polarity) = match modifier {
|
let (constness, polarity) = match modifier {
|
||||||
hir::TraitBoundModifier::Const => {
|
hir::TraitBoundModifier::Const => {
|
||||||
(ty::BoundConstness::Const, ty::ImplPolarity::Positive)
|
(ty::BoundConstness::Const, ty::PredicatePolarity::Positive)
|
||||||
}
|
}
|
||||||
hir::TraitBoundModifier::MaybeConst => {
|
hir::TraitBoundModifier::MaybeConst => {
|
||||||
(ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive)
|
(ty::BoundConstness::ConstIfConst, ty::PredicatePolarity::Positive)
|
||||||
}
|
}
|
||||||
hir::TraitBoundModifier::None => {
|
hir::TraitBoundModifier::None => {
|
||||||
(ty::BoundConstness::NotConst, ty::ImplPolarity::Positive)
|
(ty::BoundConstness::NotConst, ty::PredicatePolarity::Positive)
|
||||||
}
|
}
|
||||||
hir::TraitBoundModifier::Negative => {
|
hir::TraitBoundModifier::Negative => {
|
||||||
(ty::BoundConstness::NotConst, ty::ImplPolarity::Negative)
|
(ty::BoundConstness::NotConst, ty::PredicatePolarity::Negative)
|
||||||
}
|
}
|
||||||
hir::TraitBoundModifier::Maybe => continue,
|
hir::TraitBoundModifier::Maybe => continue,
|
||||||
};
|
};
|
||||||
|
|
|
@ -673,7 +673,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
trait_ref: &hir::TraitRef<'tcx>,
|
trait_ref: &hir::TraitRef<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
constness: ty::BoundConstness,
|
constness: ty::BoundConstness,
|
||||||
polarity: ty::ImplPolarity,
|
polarity: ty::PredicatePolarity,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
bounds: &mut Bounds<'tcx>,
|
bounds: &mut Bounds<'tcx>,
|
||||||
only_self_bounds: OnlySelfBounds,
|
only_self_bounds: OnlySelfBounds,
|
||||||
|
@ -710,7 +710,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
// Don't register additional associated type bounds for negative bounds,
|
// Don't register additional associated type bounds for negative bounds,
|
||||||
// since we should have emitten an error for them earlier, and they will
|
// since we should have emitten an error for them earlier, and they will
|
||||||
// not be well-formed!
|
// not be well-formed!
|
||||||
if polarity == ty::ImplPolarity::Negative {
|
if polarity != ty::PredicatePolarity::Positive {
|
||||||
assert!(
|
assert!(
|
||||||
self.tcx().dcx().has_errors().is_some(),
|
self.tcx().dcx().has_errors().is_some(),
|
||||||
"negative trait bounds should not have bindings",
|
"negative trait bounds should not have bindings",
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
&trait_bound.trait_ref,
|
&trait_bound.trait_ref,
|
||||||
trait_bound.span,
|
trait_bound.span,
|
||||||
ty::BoundConstness::NotConst,
|
ty::BoundConstness::NotConst,
|
||||||
ty::ImplPolarity::Positive,
|
ty::PredicatePolarity::Positive,
|
||||||
dummy_self,
|
dummy_self,
|
||||||
&mut bounds,
|
&mut bounds,
|
||||||
// True so we don't populate `bounds` with associated type bounds, even
|
// True so we don't populate `bounds` with associated type bounds, even
|
||||||
|
@ -60,7 +60,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
let bound_pred = pred.kind();
|
let bound_pred = pred.kind();
|
||||||
match bound_pred.skip_binder() {
|
match bound_pred.skip_binder() {
|
||||||
ty::ClauseKind::Trait(trait_pred) => {
|
ty::ClauseKind::Trait(trait_pred) => {
|
||||||
assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
|
assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
|
||||||
trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span));
|
trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span));
|
||||||
}
|
}
|
||||||
ty::ClauseKind::Projection(proj) => {
|
ty::ClauseKind::Projection(proj) => {
|
||||||
|
|
|
@ -435,6 +435,22 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
num_params_to_take: usize,
|
num_params_to_take: usize,
|
||||||
) -> String {
|
) -> String {
|
||||||
|
let is_in_a_method_call = self
|
||||||
|
.tcx
|
||||||
|
.hir()
|
||||||
|
.parent_iter(self.path_segment.hir_id)
|
||||||
|
.skip(1)
|
||||||
|
.find_map(|(_, node)| match node {
|
||||||
|
hir::Node::Expr(expr) => Some(expr),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.is_some_and(|expr| {
|
||||||
|
matches!(
|
||||||
|
expr.kind,
|
||||||
|
hir::ExprKind::MethodCall(hir::PathSegment { args: Some(_), .. }, ..)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(hir::Node::fn_sig);
|
let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(hir::Node::fn_sig);
|
||||||
let is_used_in_input = |def_id| {
|
let is_used_in_input = |def_id| {
|
||||||
fn_sig.is_some_and(|fn_sig| {
|
fn_sig.is_some_and(|fn_sig| {
|
||||||
|
@ -453,14 +469,17 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
||||||
.skip(self.params_offset + self.num_provided_type_or_const_args())
|
.skip(self.params_offset + self.num_provided_type_or_const_args())
|
||||||
.take(num_params_to_take)
|
.take(num_params_to_take)
|
||||||
.map(|param| match param.kind {
|
.map(|param| match param.kind {
|
||||||
// This is being inferred from the item's inputs, no need to set it.
|
// If it's in method call (turbofish), it might be inferred from the expression (e.g. `.collect::<Vec<_>>()`)
|
||||||
ty::GenericParamDefKind::Type { .. } if is_used_in_input(param.def_id) => {
|
// If it is being inferred from the item's inputs, no need to set it.
|
||||||
"_".to_string()
|
ty::GenericParamDefKind::Type { .. }
|
||||||
|
if is_in_a_method_call || is_used_in_input(param.def_id) =>
|
||||||
|
{
|
||||||
|
"_"
|
||||||
}
|
}
|
||||||
_ => param.name.to_string(),
|
_ => param.name.as_str(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.intersperse(", ")
|
||||||
.join(", ")
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_unbound_associated_types(&self) -> Vec<String> {
|
fn get_unbound_associated_types(&self) -> Vec<String> {
|
||||||
|
|
|
@ -103,6 +103,8 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {
|
||||||
*[other] {" "}in the current scope
|
*[other] {" "}in the current scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hir_typeck_note_caller_chooses_ty_for_ty_param = the caller chooses a type for `{$ty_param_name}` which can be different from `{$found_ty}`
|
||||||
|
|
||||||
hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
|
hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
|
||||||
|
|
||||||
hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}`
|
hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}`
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rustc_middle::ty::Ty;
|
||||||
use rustc_span::{
|
use rustc_span::{
|
||||||
edition::{Edition, LATEST_STABLE_EDITION},
|
edition::{Edition, LATEST_STABLE_EDITION},
|
||||||
symbol::Ident,
|
symbol::Ident,
|
||||||
Span,
|
Span, Symbol,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -614,3 +614,10 @@ pub struct SuggestConvertViaMethod<'tcx> {
|
||||||
pub expected: Ty<'tcx>,
|
pub expected: Ty<'tcx>,
|
||||||
pub found: Ty<'tcx>,
|
pub found: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[note(hir_typeck_note_caller_chooses_ty_for_ty_param)]
|
||||||
|
pub struct NoteCallerChoosesTyForTyParam<'tcx> {
|
||||||
|
pub ty_param_name: Symbol,
|
||||||
|
pub found_ty: Ty<'tcx>,
|
||||||
|
}
|
||||||
|
|
|
@ -3099,7 +3099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
cause.clone().derived_cause(
|
cause.clone().derived_cause(
|
||||||
ty::Binder::dummy(ty::TraitPredicate {
|
ty::Binder::dummy(ty::TraitPredicate {
|
||||||
trait_ref: impl_trait_ref,
|
trait_ref: impl_trait_ref,
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
}),
|
}),
|
||||||
|derived| {
|
|derived| {
|
||||||
traits::ImplDerivedObligation(Box::new(
|
traits::ImplDerivedObligation(Box::new(
|
||||||
|
|
|
@ -888,7 +888,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.dcx(),
|
self.dcx(),
|
||||||
errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected },
|
errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected },
|
||||||
);
|
);
|
||||||
self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
|
self.try_suggest_return_impl_trait(err, expected, found, fn_id);
|
||||||
|
self.note_caller_chooses_ty_for_ty_param(err, expected, found);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,6 +899,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn note_caller_chooses_ty_for_ty_param(
|
||||||
|
&self,
|
||||||
|
diag: &mut Diag<'_>,
|
||||||
|
expected: Ty<'tcx>,
|
||||||
|
found: Ty<'tcx>,
|
||||||
|
) {
|
||||||
|
if let ty::Param(expected_ty_as_param) = expected.kind() {
|
||||||
|
diag.subdiagnostic(
|
||||||
|
self.dcx(),
|
||||||
|
errors::NoteCallerChoosesTyForTyParam {
|
||||||
|
ty_param_name: expected_ty_as_param.name,
|
||||||
|
found_ty: found,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// check whether the return type is a generic type with a trait bound
|
/// check whether the return type is a generic type with a trait bound
|
||||||
/// only suggest this if the generic param is not present in the arguments
|
/// only suggest this if the generic param is not present in the arguments
|
||||||
/// if this is true, hint them towards changing the return type to `impl Trait`
|
/// if this is true, hint them towards changing the return type to `impl Trait`
|
||||||
|
|
|
@ -872,7 +872,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
match pred.kind().skip_binder() {
|
match pred.kind().skip_binder() {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||||
Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
|
Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
|
||||||
&& pred.polarity == ty::ImplPolarity::Positive
|
&& pred.polarity == ty::PredicatePolarity::Positive
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -3364,7 +3364,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
"inherent impls can't be candidates, only trait impls can be",
|
"inherent impls can't be candidates, only trait impls can be",
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.filter(|header| header.polarity == ty::ImplPolarity::Negative)
|
.filter(|header| header.polarity != ty::ImplPolarity::Positive)
|
||||||
.any(|header| {
|
.any(|header| {
|
||||||
let imp = header.trait_ref.instantiate_identity();
|
let imp = header.trait_ref.instantiate_identity();
|
||||||
let imp_simp =
|
let imp_simp =
|
||||||
|
|
|
@ -306,7 +306,7 @@ impl<T> Trait<T> for X {
|
||||||
.any(|(pred, _span)| match pred.kind().skip_binder() {
|
.any(|(pred, _span)| match pred.kind().skip_binder() {
|
||||||
ty::ClauseKind::Trait(trait_predicate)
|
ty::ClauseKind::Trait(trait_predicate)
|
||||||
if trait_predicate.polarity
|
if trait_predicate.polarity
|
||||||
== ty::ImplPolarity::Positive =>
|
== ty::PredicatePolarity::Positive =>
|
||||||
{
|
{
|
||||||
trait_predicate.def_id() == def_id
|
trait_predicate.def_id() == def_id
|
||||||
}
|
}
|
||||||
|
@ -420,7 +420,7 @@ impl<T> Trait<T> for X {
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if trait_predicate.polarity != ty::ImplPolarity::Positive {
|
if trait_predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let def_id = trait_predicate.def_id();
|
let def_id = trait_predicate.def_id();
|
||||||
|
|
|
@ -209,7 +209,7 @@ impl<'tcx> FulfillmentError<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PolyTraitObligation<'tcx> {
|
impl<'tcx> PolyTraitObligation<'tcx> {
|
||||||
pub fn polarity(&self) -> ty::ImplPolarity {
|
pub fn polarity(&self) -> ty::PredicatePolarity {
|
||||||
self.predicate.skip_binder().polarity
|
self.predicate.skip_binder().polarity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -270,7 +270,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
||||||
match bound_clause.skip_binder() {
|
match bound_clause.skip_binder() {
|
||||||
ty::ClauseKind::Trait(data) => {
|
ty::ClauseKind::Trait(data) => {
|
||||||
// Negative trait bounds do not imply any supertrait bounds
|
// Negative trait bounds do not imply any supertrait bounds
|
||||||
if data.polarity == ty::ImplPolarity::Negative {
|
if data.polarity != ty::PredicatePolarity::Positive {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Get predicates implied by the trait, or only super predicates if we only care about self predicates.
|
// Get predicates implied by the trait, or only super predicates if we only care about self predicates.
|
||||||
|
|
|
@ -726,7 +726,7 @@ fn type_implements_negative_copy_modulo_regions<'tcx>(
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, None), [ty]);
|
let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, None), [ty]);
|
||||||
let pred = ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Negative };
|
let pred = ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Negative };
|
||||||
let obligation = traits::Obligation {
|
let obligation = traits::Obligation {
|
||||||
cause: traits::ObligationCause::dummy(),
|
cause: traits::ObligationCause::dummy(),
|
||||||
param_env,
|
param_env,
|
||||||
|
|
|
@ -234,6 +234,7 @@ trivial! {
|
||||||
Option<rustc_middle::middle::stability::DeprecationEntry>,
|
Option<rustc_middle::middle::stability::DeprecationEntry>,
|
||||||
Option<rustc_middle::ty::Destructor>,
|
Option<rustc_middle::ty::Destructor>,
|
||||||
Option<rustc_middle::ty::ImplTraitInTraitData>,
|
Option<rustc_middle::ty::ImplTraitInTraitData>,
|
||||||
|
Option<rustc_middle::ty::ScalarInt>,
|
||||||
Option<rustc_span::def_id::CrateNum>,
|
Option<rustc_span::def_id::CrateNum>,
|
||||||
Option<rustc_span::def_id::DefId>,
|
Option<rustc_span::def_id::DefId>,
|
||||||
Option<rustc_span::def_id::LocalDefId>,
|
Option<rustc_span::def_id::LocalDefId>,
|
||||||
|
|
|
@ -13,6 +13,7 @@ use rustc_query_system::query::DefIdCacheSelector;
|
||||||
use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
|
use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
|
||||||
use rustc_span::symbol::{Ident, Symbol};
|
use rustc_span::symbol::{Ident, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
use rustc_target::abi;
|
||||||
|
|
||||||
/// Placeholder for `CrateNum`'s "local" counterpart
|
/// Placeholder for `CrateNum`'s "local" counterpart
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -502,6 +503,14 @@ impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Key for (Ty<'tcx>, abi::VariantIdx) {
|
||||||
|
type CacheSelector = DefaultCacheSelector<Self>;
|
||||||
|
|
||||||
|
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
|
||||||
|
DUMMY_SP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
|
impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
|
||||||
type CacheSelector = DefaultCacheSelector<Self>;
|
type CacheSelector = DefaultCacheSelector<Self>;
|
||||||
|
|
||||||
|
|
|
@ -1062,6 +1062,13 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes the tag (if any) for a given type and variant.
|
||||||
|
query tag_for_variant(
|
||||||
|
key: (Ty<'tcx>, abi::VariantIdx)
|
||||||
|
) -> Option<ty::ScalarInt> {
|
||||||
|
desc { "computing variant tag for enum" }
|
||||||
|
}
|
||||||
|
|
||||||
/// Evaluates a constant and returns the computed allocation.
|
/// Evaluates a constant and returns the computed allocation.
|
||||||
///
|
///
|
||||||
/// **Do not use this** directly, use the `eval_to_const_value` or `eval_to_valtree` instead.
|
/// **Do not use this** directly, use the `eval_to_const_value` or `eval_to_valtree` instead.
|
||||||
|
|
|
@ -27,8 +27,8 @@ use crate::traits::solve::{
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind,
|
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind,
|
||||||
ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate,
|
ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate,
|
||||||
PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
|
PredicateKind, PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty,
|
||||||
TypeVisitable, Visibility,
|
TyKind, TyVid, TypeVisitable, Visibility,
|
||||||
};
|
};
|
||||||
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
||||||
use rustc_ast::{self as ast, attr};
|
use rustc_ast::{self as ast, attr};
|
||||||
|
@ -1526,7 +1526,7 @@ macro_rules! nop_slice_lift {
|
||||||
nop_slice_lift! {ty::ValTree<'a> => ty::ValTree<'tcx>}
|
nop_slice_lift! {ty::ValTree<'a> => ty::ValTree<'tcx>}
|
||||||
|
|
||||||
TrivialLiftImpls! {
|
TrivialLiftImpls! {
|
||||||
ImplPolarity, Promoted
|
ImplPolarity, PredicatePolarity, Promoted
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! sty_debug_print {
|
macro_rules! sty_debug_print {
|
||||||
|
@ -1833,7 +1833,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
trait_predicate.trait_ref.def_id == future_trait
|
trait_predicate.trait_ref.def_id == future_trait
|
||||||
&& trait_predicate.polarity == ImplPolarity::Positive
|
&& trait_predicate.polarity == PredicatePolarity::Positive
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl<T> ExpectedFound<T> {
|
||||||
pub enum TypeError<'tcx> {
|
pub enum TypeError<'tcx> {
|
||||||
Mismatch,
|
Mismatch,
|
||||||
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
|
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
|
||||||
PolarityMismatch(ExpectedFound<ty::ImplPolarity>),
|
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
|
||||||
UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
|
UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
|
||||||
AbiMismatch(ExpectedFound<abi::Abi>),
|
AbiMismatch(ExpectedFound<abi::Abi>),
|
||||||
Mutability,
|
Mutability,
|
||||||
|
|
|
@ -345,11 +345,16 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
||||||
ty::Array(inner, len)
|
ty::Array(inner, len)
|
||||||
if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts =>
|
if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts =>
|
||||||
{
|
{
|
||||||
|
let len_eval = len.try_eval_target_usize(tcx, param_env);
|
||||||
|
if len_eval == Some(0) {
|
||||||
|
return Ok(SizeSkeleton::Known(Size::from_bytes(0)));
|
||||||
|
}
|
||||||
|
|
||||||
match SizeSkeleton::compute(inner, tcx, param_env)? {
|
match SizeSkeleton::compute(inner, tcx, param_env)? {
|
||||||
// This may succeed because the multiplication of two types may overflow
|
// This may succeed because the multiplication of two types may overflow
|
||||||
// but a single size of a nested array will not.
|
// but a single size of a nested array will not.
|
||||||
SizeSkeleton::Known(s) => {
|
SizeSkeleton::Known(s) => {
|
||||||
if let Some(c) = len.try_eval_target_usize(tcx, param_env) {
|
if let Some(c) = len_eval {
|
||||||
let size = s
|
let size = s
|
||||||
.bytes()
|
.bytes()
|
||||||
.checked_mul(c)
|
.checked_mul(c)
|
||||||
|
|
|
@ -280,17 +280,6 @@ pub enum ImplPolarity {
|
||||||
Reservation,
|
Reservation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImplPolarity {
|
|
||||||
/// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
|
|
||||||
pub fn flip(&self) -> Option<ImplPolarity> {
|
|
||||||
match self {
|
|
||||||
ImplPolarity::Positive => Some(ImplPolarity::Negative),
|
|
||||||
ImplPolarity::Negative => Some(ImplPolarity::Positive),
|
|
||||||
ImplPolarity::Reservation => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for ImplPolarity {
|
impl fmt::Display for ImplPolarity {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -301,6 +290,37 @@ impl fmt::Display for ImplPolarity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Polarity for a trait predicate. May either be negative or positive.
|
||||||
|
/// Distinguished from [`ImplPolarity`] since we never compute goals with
|
||||||
|
/// "reservation" level.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
||||||
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
|
pub enum PredicatePolarity {
|
||||||
|
/// `Type: Trait`
|
||||||
|
Positive,
|
||||||
|
/// `Type: !Trait`
|
||||||
|
Negative,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PredicatePolarity {
|
||||||
|
/// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
|
||||||
|
pub fn flip(&self) -> PredicatePolarity {
|
||||||
|
match self {
|
||||||
|
PredicatePolarity::Positive => PredicatePolarity::Negative,
|
||||||
|
PredicatePolarity::Negative => PredicatePolarity::Positive,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for PredicatePolarity {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Positive => f.write_str("positive"),
|
||||||
|
Self::Negative => f.write_str("negative"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
||||||
#[derive(TypeFoldable, TypeVisitable)]
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
pub enum Asyncness {
|
pub enum Asyncness {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::cmp::Ordering;
|
||||||
use crate::ty::visit::TypeVisitableExt;
|
use crate::ty::visit::TypeVisitableExt;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArg, GenericArgs,
|
self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArg, GenericArgs,
|
||||||
GenericArgsRef, ImplPolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
|
GenericArgsRef, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
|
pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
|
||||||
|
@ -70,7 +70,7 @@ impl<'tcx> Predicate<'tcx> {
|
||||||
polarity,
|
polarity,
|
||||||
})) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
|
})) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
|
||||||
trait_ref,
|
trait_ref,
|
||||||
polarity: polarity.flip()?,
|
polarity: polarity.flip(),
|
||||||
}))),
|
}))),
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -663,7 +663,7 @@ pub struct TraitPredicate<'tcx> {
|
||||||
/// exist via a series of predicates.)
|
/// exist via a series of predicates.)
|
||||||
///
|
///
|
||||||
/// If polarity is Reserved: that's a bug.
|
/// If polarity is Reserved: that's a bug.
|
||||||
pub polarity: ImplPolarity,
|
pub polarity: PredicatePolarity,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
|
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
|
||||||
|
@ -693,7 +693,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn polarity(self) -> ImplPolarity {
|
pub fn polarity(self) -> PredicatePolarity {
|
||||||
self.skip_binder().polarity
|
self.skip_binder().polarity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -907,7 +907,7 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
|
||||||
impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
|
impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> {
|
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> {
|
||||||
TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive }
|
TraitPredicate { trait_ref: self, polarity: PredicatePolarity::Positive }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,7 +940,7 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef
|
||||||
fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
|
fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
|
||||||
self.map_bound(|trait_ref| TraitPredicate {
|
self.map_bound(|trait_ref| TraitPredicate {
|
||||||
trait_ref,
|
trait_ref,
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -995,11 +995,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
// Don't print `+ Sized`, but rather `+ ?Sized` if absent.
|
// Don't print `+ Sized`, but rather `+ ?Sized` if absent.
|
||||||
if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
|
if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
|
||||||
match pred.polarity {
|
match pred.polarity {
|
||||||
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => {
|
ty::PredicatePolarity::Positive => {
|
||||||
has_sized_bound = true;
|
has_sized_bound = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ty::ImplPolarity::Negative => has_negative_sized_bound = true,
|
ty::PredicatePolarity::Negative => has_negative_sized_bound = true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1020,7 +1020,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
|
|
||||||
self.insert_trait_and_projection(
|
self.insert_trait_and_projection(
|
||||||
trait_ref,
|
trait_ref,
|
||||||
ty::ImplPolarity::Positive,
|
ty::PredicatePolarity::Positive,
|
||||||
Some(proj_ty),
|
Some(proj_ty),
|
||||||
&mut traits,
|
&mut traits,
|
||||||
&mut fn_traits,
|
&mut fn_traits,
|
||||||
|
@ -1085,7 +1085,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
_ => {
|
_ => {
|
||||||
if entry.has_fn_once {
|
if entry.has_fn_once {
|
||||||
traits
|
traits
|
||||||
.entry((fn_once_trait_ref, ty::ImplPolarity::Positive))
|
.entry((fn_once_trait_ref, ty::PredicatePolarity::Positive))
|
||||||
.or_default()
|
.or_default()
|
||||||
.extend(
|
.extend(
|
||||||
// Group the return ty with its def id, if we had one.
|
// Group the return ty with its def id, if we had one.
|
||||||
|
@ -1095,10 +1095,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if let Some(trait_ref) = entry.fn_mut_trait_ref {
|
if let Some(trait_ref) = entry.fn_mut_trait_ref {
|
||||||
traits.entry((trait_ref, ty::ImplPolarity::Positive)).or_default();
|
traits.entry((trait_ref, ty::PredicatePolarity::Positive)).or_default();
|
||||||
}
|
}
|
||||||
if let Some(trait_ref) = entry.fn_trait_ref {
|
if let Some(trait_ref) = entry.fn_trait_ref {
|
||||||
traits.entry((trait_ref, ty::ImplPolarity::Positive)).or_default();
|
traits.entry((trait_ref, ty::PredicatePolarity::Positive)).or_default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1114,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
self.wrap_binder(&trait_ref, |trait_ref, cx| {
|
self.wrap_binder(&trait_ref, |trait_ref, cx| {
|
||||||
define_scoped_cx!(cx);
|
define_scoped_cx!(cx);
|
||||||
|
|
||||||
if polarity == ty::ImplPolarity::Negative {
|
if polarity == ty::PredicatePolarity::Negative {
|
||||||
p!("!");
|
p!("!");
|
||||||
}
|
}
|
||||||
p!(print(trait_ref.print_only_trait_name()));
|
p!(print(trait_ref.print_only_trait_name()));
|
||||||
|
@ -1223,10 +1223,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
fn insert_trait_and_projection(
|
fn insert_trait_and_projection(
|
||||||
&mut self,
|
&mut self,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
polarity: ty::ImplPolarity,
|
polarity: ty::PredicatePolarity,
|
||||||
proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>,
|
proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>,
|
||||||
traits: &mut FxIndexMap<
|
traits: &mut FxIndexMap<
|
||||||
(ty::PolyTraitRef<'tcx>, ty::ImplPolarity),
|
(ty::PolyTraitRef<'tcx>, ty::PredicatePolarity),
|
||||||
FxIndexMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
|
FxIndexMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
|
||||||
>,
|
>,
|
||||||
fn_traits: &mut FxIndexMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>,
|
fn_traits: &mut FxIndexMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>,
|
||||||
|
@ -1236,7 +1236,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
// If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
|
// If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
|
||||||
// super-trait ref and record it there.
|
// super-trait ref and record it there.
|
||||||
// We skip negative Fn* bounds since they can't use parenthetical notation anyway.
|
// We skip negative Fn* bounds since they can't use parenthetical notation anyway.
|
||||||
if polarity == ty::ImplPolarity::Positive
|
if polarity == ty::PredicatePolarity::Positive
|
||||||
&& let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait()
|
&& let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait()
|
||||||
{
|
{
|
||||||
// If we have a FnOnce, then insert it into
|
// If we have a FnOnce, then insert it into
|
||||||
|
@ -3139,7 +3139,7 @@ define_print_and_forward_display! {
|
||||||
|
|
||||||
TraitPredPrintModifiersAndPath<'tcx> {
|
TraitPredPrintModifiersAndPath<'tcx> {
|
||||||
p!(pretty_print_bound_constness(self.0.trait_ref));
|
p!(pretty_print_bound_constness(self.0.trait_ref));
|
||||||
if let ty::ImplPolarity::Negative = self.0.polarity {
|
if let ty::PredicatePolarity::Negative = self.0.polarity {
|
||||||
p!("!")
|
p!("!")
|
||||||
}
|
}
|
||||||
p!(print(self.0.trait_ref.print_only_trait_path()));
|
p!(print(self.0.trait_ref.print_only_trait_path()));
|
||||||
|
@ -3172,7 +3172,7 @@ define_print_and_forward_display! {
|
||||||
ty::TraitPredicate<'tcx> {
|
ty::TraitPredicate<'tcx> {
|
||||||
p!(print(self.trait_ref.self_ty()), ": ");
|
p!(print(self.trait_ref.self_ty()), ": ");
|
||||||
p!(pretty_print_bound_constness(self.trait_ref));
|
p!(pretty_print_bound_constness(self.trait_ref));
|
||||||
if let ty::ImplPolarity::Negative = self.polarity {
|
if let ty::PredicatePolarity::Negative = self.polarity {
|
||||||
p!("!");
|
p!("!");
|
||||||
}
|
}
|
||||||
p!(print(self.trait_ref.print_trait_sugared()))
|
p!(print(self.trait_ref.print_trait_sugared()))
|
||||||
|
|
|
@ -769,12 +769,12 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Relate<'tcx> for ty::ImplPolarity {
|
impl<'tcx> Relate<'tcx> for ty::PredicatePolarity {
|
||||||
fn relate<R: TypeRelation<'tcx>>(
|
fn relate<R: TypeRelation<'tcx>>(
|
||||||
_relation: &mut R,
|
_relation: &mut R,
|
||||||
a: ty::ImplPolarity,
|
a: ty::PredicatePolarity,
|
||||||
b: ty::ImplPolarity,
|
b: ty::PredicatePolarity,
|
||||||
) -> RelateResult<'tcx, ty::ImplPolarity> {
|
) -> RelateResult<'tcx, ty::PredicatePolarity> {
|
||||||
if a != b { Err(TypeError::PolarityMismatch(expected_found(a, b))) } else { Ok(a) }
|
if a != b { Err(TypeError::PolarityMismatch(expected_found(a, b))) } else { Ok(a) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,52 +2,22 @@
|
||||||
//!
|
//!
|
||||||
//! Currently, this pass only propagates scalar values.
|
//! Currently, this pass only propagates scalar values.
|
||||||
|
|
||||||
use rustc_const_eval::interpret::{
|
use rustc_const_eval::const_eval::{throw_machine_stop_str, DummyMachine};
|
||||||
HasStaticRootDefId, ImmTy, Immediate, InterpCx, OpTy, PlaceTy, PointerArithmetic, Projectable,
|
use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable};
|
||||||
};
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult, Scalar};
|
use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
||||||
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::query::TyCtxtAt;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_mir_dataflow::value_analysis::{
|
use rustc_mir_dataflow::value_analysis::{
|
||||||
Map, PlaceIndex, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
|
Map, PlaceIndex, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
|
||||||
};
|
};
|
||||||
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, Results, ResultsVisitor};
|
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, Results, ResultsVisitor};
|
||||||
use rustc_span::def_id::DefId;
|
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT};
|
use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT};
|
||||||
|
|
||||||
/// Macro for machine-specific `InterpError` without allocation.
|
|
||||||
/// (These will never be shown to the user, but they help diagnose ICEs.)
|
|
||||||
pub(crate) macro throw_machine_stop_str($($tt:tt)*) {{
|
|
||||||
// We make a new local type for it. The type itself does not carry any information,
|
|
||||||
// but its vtable (for the `MachineStopType` trait) does.
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Zst;
|
|
||||||
// Printing this type shows the desired string.
|
|
||||||
impl std::fmt::Display for Zst {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, $($tt)*)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl rustc_middle::mir::interpret::MachineStopType for Zst {
|
|
||||||
fn diagnostic_message(&self) -> rustc_errors::DiagMessage {
|
|
||||||
self.to_string().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_args(
|
|
||||||
self: Box<Self>,
|
|
||||||
_: &mut dyn FnMut(rustc_errors::DiagArgName, rustc_errors::DiagArgValue),
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
throw_machine_stop!(Zst)
|
|
||||||
}}
|
|
||||||
|
|
||||||
// These constants are somewhat random guesses and have not been optimized.
|
// These constants are somewhat random guesses and have not been optimized.
|
||||||
// If `tcx.sess.mir_opt_level() >= 4`, we ignore the limits (this can become very expensive).
|
// If `tcx.sess.mir_opt_level() >= 4`, we ignore the limits (this can become very expensive).
|
||||||
const BLOCK_LIMIT: usize = 100;
|
const BLOCK_LIMIT: usize = 100;
|
||||||
|
@ -888,165 +858,3 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct DummyMachine;
|
|
||||||
|
|
||||||
impl HasStaticRootDefId for DummyMachine {
|
|
||||||
fn static_def_id(&self) -> Option<rustc_hir::def_id::LocalDefId> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine {
|
|
||||||
rustc_const_eval::interpret::compile_time_machine!(<'mir, 'tcx>);
|
|
||||||
type MemoryKind = !;
|
|
||||||
const PANIC_ON_ALLOC_FAIL: bool = true;
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
|
||||||
false // no reason to enforce alignment
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn before_access_global(
|
|
||||||
_tcx: TyCtxtAt<'tcx>,
|
|
||||||
_machine: &Self,
|
|
||||||
_alloc_id: AllocId,
|
|
||||||
alloc: ConstAllocation<'tcx>,
|
|
||||||
_static_def_id: Option<DefId>,
|
|
||||||
is_write: bool,
|
|
||||||
) -> InterpResult<'tcx> {
|
|
||||||
if is_write {
|
|
||||||
throw_machine_stop_str!("can't write to global");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the static allocation is mutable, then we can't const prop it as its content
|
|
||||||
// might be different at runtime.
|
|
||||||
if alloc.inner().mutability.is_mut() {
|
|
||||||
throw_machine_stop_str!("can't access mutable globals in ConstProp");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_mir_or_eval_fn(
|
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
|
||||||
_instance: ty::Instance<'tcx>,
|
|
||||||
_abi: rustc_target::spec::abi::Abi,
|
|
||||||
_args: &[rustc_const_eval::interpret::FnArg<'tcx, Self::Provenance>],
|
|
||||||
_destination: &rustc_const_eval::interpret::MPlaceTy<'tcx, Self::Provenance>,
|
|
||||||
_target: Option<BasicBlock>,
|
|
||||||
_unwind: UnwindAction,
|
|
||||||
) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn panic_nounwind(
|
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
|
||||||
_msg: &str,
|
|
||||||
) -> interpret::InterpResult<'tcx> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_intrinsic(
|
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
|
||||||
_instance: ty::Instance<'tcx>,
|
|
||||||
_args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>],
|
|
||||||
_destination: &rustc_const_eval::interpret::MPlaceTy<'tcx, Self::Provenance>,
|
|
||||||
_target: Option<BasicBlock>,
|
|
||||||
_unwind: UnwindAction,
|
|
||||||
) -> interpret::InterpResult<'tcx> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_panic(
|
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
|
||||||
_msg: &rustc_middle::mir::AssertMessage<'tcx>,
|
|
||||||
_unwind: UnwindAction,
|
|
||||||
) -> interpret::InterpResult<'tcx> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn binary_ptr_op(
|
|
||||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
|
||||||
bin_op: BinOp,
|
|
||||||
left: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>,
|
|
||||||
right: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>,
|
|
||||||
) -> interpret::InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)> {
|
|
||||||
use rustc_middle::mir::BinOp::*;
|
|
||||||
Ok(match bin_op {
|
|
||||||
Eq | Ne | Lt | Le | Gt | Ge => {
|
|
||||||
// Types can differ, e.g. fn ptrs with different `for`.
|
|
||||||
assert_eq!(left.layout.abi, right.layout.abi);
|
|
||||||
let size = ecx.pointer_size();
|
|
||||||
// Just compare the bits. ScalarPairs are compared lexicographically.
|
|
||||||
// We thus always compare pairs and simply fill scalars up with 0.
|
|
||||||
// If the pointer has provenance, `to_bits` will return `Err` and we bail out.
|
|
||||||
let left = match **left {
|
|
||||||
Immediate::Scalar(l) => (l.to_bits(size)?, 0),
|
|
||||||
Immediate::ScalarPair(l1, l2) => (l1.to_bits(size)?, l2.to_bits(size)?),
|
|
||||||
Immediate::Uninit => panic!("we should never see uninit data here"),
|
|
||||||
};
|
|
||||||
let right = match **right {
|
|
||||||
Immediate::Scalar(r) => (r.to_bits(size)?, 0),
|
|
||||||
Immediate::ScalarPair(r1, r2) => (r1.to_bits(size)?, r2.to_bits(size)?),
|
|
||||||
Immediate::Uninit => panic!("we should never see uninit data here"),
|
|
||||||
};
|
|
||||||
let res = match bin_op {
|
|
||||||
Eq => left == right,
|
|
||||||
Ne => left != right,
|
|
||||||
Lt => left < right,
|
|
||||||
Le => left <= right,
|
|
||||||
Gt => left > right,
|
|
||||||
Ge => left >= right,
|
|
||||||
_ => bug!(),
|
|
||||||
};
|
|
||||||
(ImmTy::from_bool(res, *ecx.tcx), false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some more operations are possible with atomics.
|
|
||||||
// The return value always has the provenance of the *left* operand.
|
|
||||||
Add | Sub | BitOr | BitAnd | BitXor => {
|
|
||||||
throw_machine_stop_str!("pointer arithmetic is not handled")
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => span_bug!(ecx.cur_span(), "Invalid operator on pointers: {:?}", bin_op),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expose_ptr(
|
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
|
||||||
_ptr: interpret::Pointer<Self::Provenance>,
|
|
||||||
) -> interpret::InterpResult<'tcx> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_frame_extra(
|
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
|
||||||
_frame: rustc_const_eval::interpret::Frame<'mir, 'tcx, Self::Provenance>,
|
|
||||||
) -> interpret::InterpResult<
|
|
||||||
'tcx,
|
|
||||||
rustc_const_eval::interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
|
|
||||||
> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stack<'a>(
|
|
||||||
_ecx: &'a InterpCx<'mir, 'tcx, Self>,
|
|
||||||
) -> &'a [rustc_const_eval::interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>]
|
|
||||||
{
|
|
||||||
// Return an empty stack instead of panicking, as `cur_span` uses it to evaluate constants.
|
|
||||||
&[]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stack_mut<'a>(
|
|
||||||
_ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
|
|
||||||
) -> &'a mut Vec<
|
|
||||||
rustc_const_eval::interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
|
|
||||||
> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
//! Second, when writing constants in MIR, we do not write `Const::Slice` or `Const`
|
//! Second, when writing constants in MIR, we do not write `Const::Slice` or `Const`
|
||||||
//! that contain `AllocId`s.
|
//! that contain `AllocId`s.
|
||||||
|
|
||||||
|
use rustc_const_eval::const_eval::DummyMachine;
|
||||||
use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemoryKind};
|
use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemoryKind};
|
||||||
use rustc_const_eval::interpret::{ImmTy, InterpCx, OpTy, Projectable, Scalar};
|
use rustc_const_eval::interpret::{ImmTy, InterpCx, OpTy, Projectable, Scalar};
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
|
@ -101,7 +102,6 @@ use rustc_target::abi::{self, Abi, Size, VariantIdx, FIRST_VARIANT};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::dataflow_const_prop::DummyMachine;
|
|
||||||
use crate::ssa::{AssignedValue, SsaLocals};
|
use crate::ssa::{AssignedValue, SsaLocals};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
//! cost by `MAX_COST`.
|
//! cost by `MAX_COST`.
|
||||||
|
|
||||||
use rustc_arena::DroplessArena;
|
use rustc_arena::DroplessArena;
|
||||||
|
use rustc_const_eval::const_eval::DummyMachine;
|
||||||
use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable};
|
use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
|
@ -50,7 +51,6 @@ use rustc_span::DUMMY_SP;
|
||||||
use rustc_target::abi::{TagEncoding, Variants};
|
use rustc_target::abi::{TagEncoding, Variants};
|
||||||
|
|
||||||
use crate::cost_checker::CostChecker;
|
use crate::cost_checker::CostChecker;
|
||||||
use crate::dataflow_const_prop::DummyMachine;
|
|
||||||
|
|
||||||
pub struct JumpThreading;
|
pub struct JumpThreading;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use rustc_const_eval::const_eval::DummyMachine;
|
||||||
use rustc_const_eval::interpret::{
|
use rustc_const_eval::interpret::{
|
||||||
format_interp_error, ImmTy, InterpCx, InterpResult, Projectable, Scalar,
|
format_interp_error, ImmTy, InterpCx, InterpResult, Projectable, Scalar,
|
||||||
};
|
};
|
||||||
|
@ -20,7 +21,6 @@ use rustc_middle::ty::{self, ConstInt, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisi
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::abi::{Abi, FieldIdx, HasDataLayout, Size, TargetDataLayout, VariantIdx};
|
use rustc_target::abi::{Abi, FieldIdx, HasDataLayout, Size, TargetDataLayout, VariantIdx};
|
||||||
|
|
||||||
use crate::dataflow_const_prop::DummyMachine;
|
|
||||||
use crate::errors::{AssertLint, AssertLintKind};
|
use crate::errors::{AssertLint, AssertLintKind};
|
||||||
use crate::MirLint;
|
use crate::MirLint;
|
||||||
|
|
||||||
|
|
|
@ -719,6 +719,18 @@ impl<'tcx> Stable<'tcx> for ty::ImplPolarity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::PredicatePolarity {
|
||||||
|
type T = stable_mir::ty::PredicatePolarity;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||||
|
use rustc_middle::ty::PredicatePolarity::*;
|
||||||
|
match self {
|
||||||
|
Positive => stable_mir::ty::PredicatePolarity::Positive,
|
||||||
|
Negative => stable_mir::ty::PredicatePolarity::Negative,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Stable<'tcx> for ty::Region<'tcx> {
|
impl<'tcx> Stable<'tcx> for ty::Region<'tcx> {
|
||||||
type T = stable_mir::ty::Region;
|
type T = stable_mir::ty::Region;
|
||||||
|
|
||||||
|
|
|
@ -55,17 +55,23 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
// An upper bound of the certainty of this goal, used to lower the certainty
|
// An upper bound of the certainty of this goal, used to lower the certainty
|
||||||
// of reservation impl to ambiguous during coherence.
|
// of reservation impl to ambiguous during coherence.
|
||||||
let impl_polarity = impl_trait_header.polarity;
|
let impl_polarity = impl_trait_header.polarity;
|
||||||
let maximal_certainty = match impl_polarity {
|
let maximal_certainty = match (impl_polarity, goal.predicate.polarity) {
|
||||||
ty::ImplPolarity::Positive | ty::ImplPolarity::Negative => {
|
// In intercrate mode, this is ambiguous. But outside of intercrate,
|
||||||
match impl_polarity == goal.predicate.polarity {
|
// it's not a real impl.
|
||||||
true => Certainty::Yes,
|
(ty::ImplPolarity::Reservation, _) => match ecx.solver_mode() {
|
||||||
false => return Err(NoSolution),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ty::ImplPolarity::Reservation => match ecx.solver_mode() {
|
|
||||||
SolverMode::Normal => return Err(NoSolution),
|
|
||||||
SolverMode::Coherence => Certainty::AMBIGUOUS,
|
SolverMode::Coherence => Certainty::AMBIGUOUS,
|
||||||
|
SolverMode::Normal => return Err(NoSolution),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Impl matches polarity
|
||||||
|
(ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)
|
||||||
|
| (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => Certainty::Yes,
|
||||||
|
|
||||||
|
// Impl doesn't match polarity
|
||||||
|
(ty::ImplPolarity::Positive, ty::PredicatePolarity::Negative)
|
||||||
|
| (ty::ImplPolarity::Negative, ty::PredicatePolarity::Positive) => {
|
||||||
|
return Err(NoSolution);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
|
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
|
||||||
|
@ -123,7 +129,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +174,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +197,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +211,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +225,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +257,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
let self_ty = goal.predicate.self_ty();
|
let self_ty = goal.predicate.self_ty();
|
||||||
match goal.predicate.polarity {
|
match goal.predicate.polarity {
|
||||||
// impl FnPtr for FnPtr {}
|
// impl FnPtr for FnPtr {}
|
||||||
ty::ImplPolarity::Positive => {
|
ty::PredicatePolarity::Positive => {
|
||||||
if self_ty.is_fn_ptr() {
|
if self_ty.is_fn_ptr() {
|
||||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
} else {
|
} else {
|
||||||
|
@ -259,7 +265,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// impl !FnPtr for T where T != FnPtr && T is rigid {}
|
// impl !FnPtr for T where T != FnPtr && T is rigid {}
|
||||||
ty::ImplPolarity::Negative => {
|
ty::PredicatePolarity::Negative => {
|
||||||
// If a type is rigid and not a fn ptr, then we know for certain
|
// If a type is rigid and not a fn ptr, then we know for certain
|
||||||
// that it does *not* implement `FnPtr`.
|
// that it does *not* implement `FnPtr`.
|
||||||
if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
|
if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
|
||||||
|
@ -268,10 +274,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
Err(NoSolution)
|
Err(NoSolution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME: Goal polarity should be split from impl polarity
|
|
||||||
ty::ImplPolarity::Reservation => {
|
|
||||||
bug!("we never expect a `Reservation` polarity in a trait goal")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +282,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
goal_kind: ty::ClosureKind,
|
goal_kind: ty::ClosureKind,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +318,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
goal_kind: ty::ClosureKind,
|
goal_kind: ty::ClosureKind,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +388,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +403,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +414,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +438,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,7 +462,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +484,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,7 +508,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,7 +539,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +551,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,7 +566,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,7 +603,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> {
|
) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> {
|
||||||
if goal.predicate.polarity != ty::ImplPolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
||||||
use crate::traits::project::ProjectAndUnifyResult;
|
use crate::traits::project::ProjectAndUnifyResult;
|
||||||
use rustc_infer::infer::DefineOpaqueTypes;
|
use rustc_infer::infer::DefineOpaqueTypes;
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::ty::{ImplPolarity, Region, RegionVid};
|
use rustc_middle::ty::{Region, RegionVid};
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||||
|
|
||||||
|
@ -96,9 +96,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
ty::TraitPredicate {
|
ty::TraitPredicate {
|
||||||
trait_ref,
|
trait_ref,
|
||||||
polarity: if polarity {
|
polarity: if polarity {
|
||||||
ImplPolarity::Positive
|
ty::PredicatePolarity::Positive
|
||||||
} else {
|
} else {
|
||||||
ImplPolarity::Negative
|
ty::PredicatePolarity::Negative
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
@ -258,7 +258,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
trait_ref: ty::TraitRef::new(infcx.tcx, trait_did, [ty]),
|
trait_ref: ty::TraitRef::new(infcx.tcx, trait_did, [ty]),
|
||||||
|
|
||||||
// Auto traits are positive
|
// Auto traits are positive
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let computed_preds = param_env.caller_bounds().iter().map(|c| c.as_predicate());
|
let computed_preds = param_env.caller_bounds().iter().map(|c| c.as_predicate());
|
||||||
|
@ -295,7 +295,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
}) = impl_source
|
}) = impl_source
|
||||||
{
|
{
|
||||||
// Blame 'tidy' for the weird bracket placement.
|
// Blame 'tidy' for the weird bracket placement.
|
||||||
if infcx.tcx.impl_polarity(*impl_def_id) == ty::ImplPolarity::Negative {
|
if infcx.tcx.impl_polarity(*impl_def_id) != ty::ImplPolarity::Positive {
|
||||||
debug!(
|
debug!(
|
||||||
"evaluate_nested_obligations: found explicit negative impl\
|
"evaluate_nested_obligations: found explicit negative impl\
|
||||||
{:?}, bailing out",
|
{:?}, bailing out",
|
||||||
|
|
|
@ -206,7 +206,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
ty: ty::Binder<'tcx, Ty<'tcx>>,
|
ty: ty::Binder<'tcx, Ty<'tcx>>,
|
||||||
polarity: ty::ImplPolarity,
|
polarity: ty::PredicatePolarity,
|
||||||
) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
|
) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
|
||||||
self.commit_if_ok(|_| {
|
self.commit_if_ok(|_| {
|
||||||
for trait_def_id in [
|
for trait_def_id in [
|
||||||
|
|
|
@ -245,7 +245,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
associated_ty: Option<(&'static str, Ty<'tcx>)>,
|
associated_ty: Option<(&'static str, Ty<'tcx>)>,
|
||||||
mut body_id: LocalDefId,
|
mut body_id: LocalDefId,
|
||||||
) {
|
) {
|
||||||
if trait_pred.skip_binder().polarity == ty::ImplPolarity::Negative {
|
if trait_pred.skip_binder().polarity != ty::PredicatePolarity::Positive {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4057,7 +4057,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
span,
|
span,
|
||||||
[*ty],
|
[*ty],
|
||||||
),
|
),
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
});
|
});
|
||||||
let Some(generics) = node.generics() else {
|
let Some(generics) = node.generics() else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -4802,7 +4802,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
|
||||||
Some(desc) => format!(" {desc}"),
|
Some(desc) => format!(" {desc}"),
|
||||||
None => String::new(),
|
None => String::new(),
|
||||||
};
|
};
|
||||||
if let ty::ImplPolarity::Positive = trait_predicate.polarity() {
|
if let ty::PredicatePolarity::Positive = trait_predicate.polarity() {
|
||||||
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(),
|
||||||
|
|
|
@ -1905,7 +1905,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
.all_impls(trait_pred.def_id())
|
.all_impls(trait_pred.def_id())
|
||||||
.filter_map(|def_id| {
|
.filter_map(|def_id| {
|
||||||
let imp = self.tcx.impl_trait_header(def_id).unwrap();
|
let imp = self.tcx.impl_trait_header(def_id).unwrap();
|
||||||
if imp.polarity == ty::ImplPolarity::Negative
|
if imp.polarity != ty::ImplPolarity::Positive
|
||||||
|| !self.tcx.is_user_visible_dep(def_id.krate)
|
|| !self.tcx.is_user_visible_dep(def_id.krate)
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -584,7 +584,7 @@ fn virtual_call_violations_for_method<'tcx>(
|
||||||
// implement auto traits if the underlying type does as well.
|
// implement auto traits if the underlying type does as well.
|
||||||
if let ty::ClauseKind::Trait(ty::TraitPredicate {
|
if let ty::ClauseKind::Trait(ty::TraitPredicate {
|
||||||
trait_ref: pred_trait_ref,
|
trait_ref: pred_trait_ref,
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
}) = pred.kind().skip_binder()
|
}) = pred.kind().skip_binder()
|
||||||
&& pred_trait_ref.self_ty() == tcx.types.self_param
|
&& pred_trait_ref.self_ty() == tcx.types.self_param
|
||||||
&& tcx.trait_is_auto(pred_trait_ref.def_id)
|
&& tcx.trait_is_auto(pred_trait_ref.def_id)
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
|
let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
|
||||||
|
|
||||||
// Negative trait predicates have different rules than positive trait predicates.
|
// Negative trait predicates have different rules than positive trait predicates.
|
||||||
if obligation.polarity() == ty::ImplPolarity::Negative {
|
if obligation.polarity() == ty::PredicatePolarity::Negative {
|
||||||
self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
|
self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
|
||||||
self.assemble_candidates_from_impls(obligation, &mut candidates);
|
self.assemble_candidates_from_impls(obligation, &mut candidates);
|
||||||
self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
|
self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
|
||||||
|
|
|
@ -1460,7 +1460,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
cause.span,
|
cause.span,
|
||||||
[nested_ty.into(), host_effect_param],
|
[nested_ty.into(), host_effect_param],
|
||||||
),
|
),
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
}),
|
}),
|
||||||
&mut nested,
|
&mut nested,
|
||||||
);
|
);
|
||||||
|
@ -1485,7 +1485,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
cause.span,
|
cause.span,
|
||||||
[nested_ty.into(), host_effect_param],
|
[nested_ty.into(), host_effect_param],
|
||||||
),
|
),
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
});
|
});
|
||||||
|
|
||||||
nested.push(Obligation::with_depth(
|
nested.push(Obligation::with_depth(
|
||||||
|
|
|
@ -1418,10 +1418,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
|
|
||||||
for candidate in candidates {
|
for candidate in candidates {
|
||||||
if let ImplCandidate(def_id) = candidate {
|
if let ImplCandidate(def_id) = candidate {
|
||||||
if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id)
|
match (tcx.impl_polarity(def_id), obligation.polarity()) {
|
||||||
|| obligation.polarity() == tcx.impl_polarity(def_id)
|
(ty::ImplPolarity::Reservation, _)
|
||||||
{
|
| (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)
|
||||||
result.push(candidate);
|
| (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => {
|
||||||
|
result.push(candidate);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.push(candidate);
|
result.push(candidate);
|
||||||
|
|
|
@ -363,7 +363,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||||
|
|
||||||
// Negative trait predicates don't require supertraits to hold, just
|
// Negative trait predicates don't require supertraits to hold, just
|
||||||
// that their args are WF.
|
// that their args are WF.
|
||||||
if trait_pred.polarity == ty::ImplPolarity::Negative {
|
if trait_pred.polarity == ty::PredicatePolarity::Negative {
|
||||||
self.compute_negative_trait_pred(trait_ref);
|
self.compute_negative_trait_pred(trait_ref);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,10 +174,10 @@ pub(crate) mod rustc {
|
||||||
use crate::layout::rustc::{Def, Ref};
|
use crate::layout::rustc::{Def, Ref};
|
||||||
|
|
||||||
use rustc_middle::ty::layout::LayoutError;
|
use rustc_middle::ty::layout::LayoutError;
|
||||||
use rustc_middle::ty::util::Discr;
|
|
||||||
use rustc_middle::ty::AdtDef;
|
use rustc_middle::ty::AdtDef;
|
||||||
use rustc_middle::ty::GenericArgsRef;
|
use rustc_middle::ty::GenericArgsRef;
|
||||||
use rustc_middle::ty::ParamEnv;
|
use rustc_middle::ty::ParamEnv;
|
||||||
|
use rustc_middle::ty::ScalarInt;
|
||||||
use rustc_middle::ty::VariantDef;
|
use rustc_middle::ty::VariantDef;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_span::ErrorGuaranteed;
|
use rustc_span::ErrorGuaranteed;
|
||||||
|
@ -331,14 +331,15 @@ pub(crate) mod rustc {
|
||||||
trace!(?adt_def, "treeifying enum");
|
trace!(?adt_def, "treeifying enum");
|
||||||
let mut tree = Tree::uninhabited();
|
let mut tree = Tree::uninhabited();
|
||||||
|
|
||||||
for (idx, discr) in adt_def.discriminants(tcx) {
|
for (idx, variant) in adt_def.variants().iter_enumerated() {
|
||||||
|
let tag = tcx.tag_for_variant((ty, idx));
|
||||||
tree = tree.or(Self::from_repr_c_variant(
|
tree = tree.or(Self::from_repr_c_variant(
|
||||||
ty,
|
ty,
|
||||||
*adt_def,
|
*adt_def,
|
||||||
args_ref,
|
args_ref,
|
||||||
&layout_summary,
|
&layout_summary,
|
||||||
Some(discr),
|
tag,
|
||||||
adt_def.variant(idx),
|
variant,
|
||||||
tcx,
|
tcx,
|
||||||
)?);
|
)?);
|
||||||
}
|
}
|
||||||
|
@ -393,7 +394,7 @@ pub(crate) mod rustc {
|
||||||
adt_def: AdtDef<'tcx>,
|
adt_def: AdtDef<'tcx>,
|
||||||
args_ref: GenericArgsRef<'tcx>,
|
args_ref: GenericArgsRef<'tcx>,
|
||||||
layout_summary: &LayoutSummary,
|
layout_summary: &LayoutSummary,
|
||||||
discr: Option<Discr<'tcx>>,
|
tag: Option<ScalarInt>,
|
||||||
variant_def: &'tcx VariantDef,
|
variant_def: &'tcx VariantDef,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
) -> Result<Self, Err> {
|
) -> Result<Self, Err> {
|
||||||
|
@ -403,9 +404,6 @@ pub(crate) mod rustc {
|
||||||
let min_align = repr.align.unwrap_or(Align::ONE);
|
let min_align = repr.align.unwrap_or(Align::ONE);
|
||||||
let max_align = repr.pack.unwrap_or(Align::MAX);
|
let max_align = repr.pack.unwrap_or(Align::MAX);
|
||||||
|
|
||||||
let clamp =
|
|
||||||
|align: Align| align.clamp(min_align, max_align).bytes().try_into().unwrap();
|
|
||||||
|
|
||||||
let variant_span = trace_span!(
|
let variant_span = trace_span!(
|
||||||
"treeifying variant",
|
"treeifying variant",
|
||||||
min_align = ?min_align,
|
min_align = ?min_align,
|
||||||
|
@ -419,17 +417,12 @@ pub(crate) mod rustc {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// The layout of the variant is prefixed by the discriminant, if any.
|
// The layout of the variant is prefixed by the tag, if any.
|
||||||
if let Some(discr) = discr {
|
if let Some(tag) = tag {
|
||||||
trace!(?discr, "treeifying discriminant");
|
let tag_layout =
|
||||||
let discr_layout = alloc::Layout::from_size_align(
|
alloc::Layout::from_size_align(tag.size().bytes_usize(), 1).unwrap();
|
||||||
layout_summary.discriminant_size,
|
tree = tree.then(Self::from_tag(tag, tcx));
|
||||||
clamp(layout_summary.discriminant_align),
|
variant_layout = variant_layout.extend(tag_layout).unwrap().0;
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
trace!(?discr_layout, "computed discriminant layout");
|
|
||||||
variant_layout = variant_layout.extend(discr_layout).unwrap().0;
|
|
||||||
tree = tree.then(Self::from_discr(discr, tcx, layout_summary.discriminant_size));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next come fields.
|
// Next come fields.
|
||||||
|
@ -469,18 +462,19 @@ pub(crate) mod rustc {
|
||||||
Ok(tree)
|
Ok(tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_discr(discr: Discr<'tcx>, tcx: TyCtxt<'tcx>, size: usize) -> Self {
|
pub fn from_tag(tag: ScalarInt, tcx: TyCtxt<'tcx>) -> Self {
|
||||||
use rustc_target::abi::Endian;
|
use rustc_target::abi::Endian;
|
||||||
|
let size = tag.size();
|
||||||
|
let bits = tag.to_bits(size).unwrap();
|
||||||
let bytes: [u8; 16];
|
let bytes: [u8; 16];
|
||||||
let bytes = match tcx.data_layout.endian {
|
let bytes = match tcx.data_layout.endian {
|
||||||
Endian::Little => {
|
Endian::Little => {
|
||||||
bytes = discr.val.to_le_bytes();
|
bytes = bits.to_le_bytes();
|
||||||
&bytes[..size]
|
&bytes[..size.bytes_usize()]
|
||||||
}
|
}
|
||||||
Endian::Big => {
|
Endian::Big => {
|
||||||
bytes = discr.val.to_be_bytes();
|
bytes = bits.to_be_bytes();
|
||||||
&bytes[bytes.len() - size..]
|
&bytes[bytes.len() - size.bytes_usize()..]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Self::Seq(bytes.iter().map(|&b| Self::from_bits(b)).collect())
|
Self::Seq(bytes.iter().map(|&b| Self::from_bits(b)).collect())
|
||||||
|
|
|
@ -1332,7 +1332,7 @@ pub enum AliasRelationDirection {
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct TraitPredicate {
|
pub struct TraitPredicate {
|
||||||
pub trait_ref: TraitRef,
|
pub trait_ref: TraitRef,
|
||||||
pub polarity: ImplPolarity,
|
pub polarity: PredicatePolarity,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
@ -1354,6 +1354,12 @@ pub enum ImplPolarity {
|
||||||
Reservation,
|
Reservation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum PredicatePolarity {
|
||||||
|
Positive,
|
||||||
|
Negative,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait IndexedVal {
|
pub trait IndexedVal {
|
||||||
fn to_val(index: usize) -> Self;
|
fn to_val(index: usize) -> Self;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::traits::Reveal;
|
use rustc_middle::traits::Reveal;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, TraitPredicate, Ty,
|
self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, ToPredicate, TraitPredicate, Ty,
|
||||||
TyCtxt,
|
TyCtxt,
|
||||||
};
|
};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
|
@ -502,7 +502,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
|
||||||
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
|
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
|
||||||
ClauseKind::Trait(TraitPredicate {
|
ClauseKind::Trait(TraitPredicate {
|
||||||
trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]),
|
trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]),
|
||||||
polarity: ImplPolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
})
|
})
|
||||||
.to_predicate(tcx)
|
.to_predicate(tcx)
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -9,7 +9,7 @@ use rustc_hir::{BindingAnnotation, Expr, ExprKind, FnRetTy, Param, PatKind, QPat
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, ImplPolarity, List, Region, RegionKind,
|
self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind,
|
||||||
Ty, TypeVisitableExt, TypeckResults,
|
Ty, TypeVisitableExt, TypeckResults,
|
||||||
};
|
};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
|
@ -173,7 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
|
||||||
if let Ok((ClosureKind::FnMut, _)) = cx.tcx.infer_ctxt().build().type_implements_fn_trait(
|
if let Ok((ClosureKind::FnMut, _)) = cx.tcx.infer_ctxt().build().type_implements_fn_trait(
|
||||||
cx.param_env,
|
cx.param_env,
|
||||||
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
|
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
|
||||||
ImplPolarity::Positive,
|
ty::PredicatePolarity::Positive,
|
||||||
) && path_to_local(callee).map_or(false, |l| {
|
) && path_to_local(callee).map_or(false, |l| {
|
||||||
local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
|
local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
|
||||||
}) {
|
}) {
|
||||||
|
|
|
@ -18,7 +18,7 @@ use rustc_lint::LateContext;
|
||||||
use rustc_middle::mir::Mutability;
|
use rustc_middle::mir::Mutability;
|
||||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ImplPolarity, ParamTy, ProjectionPredicate,
|
self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate,
|
||||||
TraitPredicate, Ty,
|
TraitPredicate, Ty,
|
||||||
};
|
};
|
||||||
use rustc_span::{sym, Symbol};
|
use rustc_span::{sym, Symbol};
|
||||||
|
@ -666,7 +666,7 @@ fn check_borrow_predicate<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||||
&& let Some(borrow_id) = cx.tcx.get_diagnostic_item(sym::Borrow)
|
&& let Some(borrow_id) = cx.tcx.get_diagnostic_item(sym::Borrow)
|
||||||
&& cx.tcx.predicates_of(method_def_id).predicates.iter().any(|(pred, _)| {
|
&& cx.tcx.predicates_of(method_def_id).predicates.iter().any(|(pred, _)| {
|
||||||
if let ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
|
if let ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
|
||||||
&& trait_pred.polarity == ImplPolarity::Positive
|
&& trait_pred.polarity == ty::PredicatePolarity::Positive
|
||||||
&& trait_pred.trait_ref.def_id == borrow_id
|
&& trait_pred.trait_ref.def_id == borrow_id
|
||||||
{
|
{
|
||||||
true
|
true
|
||||||
|
|
|
@ -19,6 +19,7 @@ LL | 42
|
||||||
|
|
|
|
||||||
= note: expected type parameter `u32`
|
= note: expected type parameter `u32`
|
||||||
found type `{integer}`
|
found type `{integer}`
|
||||||
|
= note: the caller chooses a type for `u32` which can be different from `i32`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
// -Zunstable-options added as test for ICE #97725 (left == right)`
|
||||||
|
// left: `Binder(<[u8; _] as std::default::Default>, [])`,
|
||||||
|
// right: `Binder(<[u8; 4] as std::default::Default>, [])
|
||||||
|
|
||||||
|
//@ compile-flags: -Zunstable-options
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
#![feature(generic_const_exprs)] //~ WARN the feature `generic_const_exprs` is incomplete
|
#![feature(generic_const_exprs)] //~ WARN the feature `generic_const_exprs` is incomplete
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/unify-fixpoint.rs:2:12
|
--> $DIR/unify-fixpoint.rs:7:12
|
||||||
|
|
|
|
||||||
LL | #![feature(generic_const_exprs)]
|
LL | #![feature(generic_const_exprs)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -5,7 +5,23 @@ struct Heap;
|
||||||
struct Vec<T, A = Heap>(
|
struct Vec<T, A = Heap>(
|
||||||
marker::PhantomData<(T,A)>);
|
marker::PhantomData<(T,A)>);
|
||||||
|
|
||||||
|
struct HashMap<K, V, S = ()>(marker::PhantomData<(K,V,S)>);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: Vec;
|
let _: Vec;
|
||||||
//~^ ERROR missing generics for struct `Vec`
|
//~^ ERROR missing generics for struct `Vec`
|
||||||
|
//~| SUGGESTION <T>
|
||||||
|
|
||||||
|
let _x = (1..10).collect::<HashMap>();
|
||||||
|
//~^ ERROR missing generics for struct `HashMap`
|
||||||
|
//~| SUGGESTION <_, _>
|
||||||
|
|
||||||
|
().extend::<[(); 0]>({
|
||||||
|
fn not_the_extend() {
|
||||||
|
let _: Vec;
|
||||||
|
//~^ ERROR missing generics for struct `Vec`
|
||||||
|
//~| SUGGESTION <T>
|
||||||
|
}
|
||||||
|
[]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0107]: missing generics for struct `Vec`
|
error[E0107]: missing generics for struct `Vec`
|
||||||
--> $DIR/generic-type-less-params-with-defaults.rs:9:12
|
--> $DIR/generic-type-less-params-with-defaults.rs:11:12
|
||||||
|
|
|
|
||||||
LL | let _: Vec;
|
LL | let _: Vec;
|
||||||
| ^^^ expected at least 1 generic argument
|
| ^^^ expected at least 1 generic argument
|
||||||
|
@ -14,6 +14,38 @@ help: add missing generic argument
|
||||||
LL | let _: Vec<T>;
|
LL | let _: Vec<T>;
|
||||||
| +++
|
| +++
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error[E0107]: missing generics for struct `HashMap`
|
||||||
|
--> $DIR/generic-type-less-params-with-defaults.rs:15:32
|
||||||
|
|
|
||||||
|
LL | let _x = (1..10).collect::<HashMap>();
|
||||||
|
| ^^^^^^^ expected at least 2 generic arguments
|
||||||
|
|
|
||||||
|
note: struct defined here, with at least 2 generic parameters: `K`, `V`
|
||||||
|
--> $DIR/generic-type-less-params-with-defaults.rs:8:8
|
||||||
|
|
|
||||||
|
LL | struct HashMap<K, V, S = ()>(marker::PhantomData<(K,V,S)>);
|
||||||
|
| ^^^^^^^ - -
|
||||||
|
help: add missing generic arguments
|
||||||
|
|
|
||||||
|
LL | let _x = (1..10).collect::<HashMap<_, _>>();
|
||||||
|
| ++++++
|
||||||
|
|
||||||
|
error[E0107]: missing generics for struct `Vec`
|
||||||
|
--> $DIR/generic-type-less-params-with-defaults.rs:21:20
|
||||||
|
|
|
||||||
|
LL | let _: Vec;
|
||||||
|
| ^^^ expected at least 1 generic argument
|
||||||
|
|
|
||||||
|
note: struct defined here, with at least 1 generic parameter: `T`
|
||||||
|
--> $DIR/generic-type-less-params-with-defaults.rs:5:8
|
||||||
|
|
|
||||||
|
LL | struct Vec<T, A = Heap>(
|
||||||
|
| ^^^ -
|
||||||
|
help: add missing generic argument
|
||||||
|
|
|
||||||
|
LL | let _: Vec<T>;
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0107`.
|
For more information about this error, try `rustc --explain E0107`.
|
||||||
|
|
10
tests/ui/parser/parser-ice-ed2021-await-105210.rs
Normal file
10
tests/ui/parser/parser-ice-ed2021-await-105210.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// ICE #105210 self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == \'\\t\'))
|
||||||
|
// ignore-tidy-tab
|
||||||
|
//@ edition:2021
|
||||||
|
pub fn main() {}
|
||||||
|
|
||||||
|
fn box () {
|
||||||
|
(( h (const {( default ( await ( await ( (move {await((((}}
|
||||||
|
//~^ ERROR mismatched closing delimiter: `}`
|
||||||
|
//~^^ ERROR mismatched closing delimiter: `}`
|
||||||
|
//~ ERROR this file contains an unclosed delimiter
|
34
tests/ui/parser/parser-ice-ed2021-await-105210.stderr
Normal file
34
tests/ui/parser/parser-ice-ed2021-await-105210.stderr
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
error: mismatched closing delimiter: `}`
|
||||||
|
--> $DIR/parser-ice-ed2021-await-105210.rs:7:58
|
||||||
|
|
|
||||||
|
LL | (( h (const {( default ( await ( await ( (move {await((((}}
|
||||||
|
| - ^^ mismatched closing delimiter
|
||||||
|
| | |
|
||||||
|
| | unclosed delimiter
|
||||||
|
| closing delimiter possibly meant for this
|
||||||
|
|
||||||
|
error: mismatched closing delimiter: `}`
|
||||||
|
--> $DIR/parser-ice-ed2021-await-105210.rs:7:43
|
||||||
|
|
|
||||||
|
LL | (( h (const {( default ( await ( await ( (move {await((((}}
|
||||||
|
| - ^ ^ mismatched closing delimiter
|
||||||
|
| | |
|
||||||
|
| | unclosed delimiter
|
||||||
|
| closing delimiter possibly meant for this
|
||||||
|
|
||||||
|
error: this file contains an unclosed delimiter
|
||||||
|
--> $DIR/parser-ice-ed2021-await-105210.rs:10:52
|
||||||
|
|
|
||||||
|
LL | fn box () {
|
||||||
|
| - unclosed delimiter
|
||||||
|
LL | (( h (const {( default ( await ( await ( (move {await((((}}
|
||||||
|
| -- - unclosed delimiter
|
||||||
|
| ||
|
||||||
|
| |unclosed delimiter
|
||||||
|
| unclosed delimiter
|
||||||
|
...
|
||||||
|
LL |
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
|
@ -10,6 +10,7 @@ LL | "this should not suggest impl Trait"
|
||||||
|
|
|
|
||||||
= note: expected type parameter `T`
|
= note: expected type parameter `T`
|
||||||
found reference `&'static str`
|
found reference `&'static str`
|
||||||
|
= note: the caller chooses a type for `T` which can be different from `&'static str`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/return-impl-trait-bad.rs:9:5
|
--> $DIR/return-impl-trait-bad.rs:9:5
|
||||||
|
@ -23,6 +24,7 @@ LL | "this will not suggest it, because that would probably be wrong"
|
||||||
|
|
|
|
||||||
= note: expected type parameter `T`
|
= note: expected type parameter `T`
|
||||||
found reference `&'static str`
|
found reference `&'static str`
|
||||||
|
= note: the caller chooses a type for `T` which can be different from `&'static str`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/return-impl-trait-bad.rs:17:5
|
--> $DIR/return-impl-trait-bad.rs:17:5
|
||||||
|
@ -37,6 +39,7 @@ LL | "don't suggest this, because Option<T> places additional constraints"
|
||||||
|
|
|
|
||||||
= note: expected type parameter `T`
|
= note: expected type parameter `T`
|
||||||
found reference `&'static str`
|
found reference `&'static str`
|
||||||
|
= note: the caller chooses a type for `T` which can be different from `&'static str`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/return-impl-trait-bad.rs:28:5
|
--> $DIR/return-impl-trait-bad.rs:28:5
|
||||||
|
@ -53,6 +56,7 @@ LL | "don't suggest this, because the generic param is used in the bound."
|
||||||
|
|
|
|
||||||
= note: expected type parameter `T`
|
= note: expected type parameter `T`
|
||||||
found reference `&'static str`
|
found reference `&'static str`
|
||||||
|
= note: the caller chooses a type for `T` which can be different from `&'static str`
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ LL | ()
|
||||||
|
|
|
|
||||||
= note: expected type parameter `T`
|
= note: expected type parameter `T`
|
||||||
found unit type `()`
|
found unit type `()`
|
||||||
|
= note: the caller chooses a type for `T` which can be different from `()`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/return-impl-trait.rs:23:5
|
--> $DIR/return-impl-trait.rs:23:5
|
||||||
|
@ -28,6 +29,7 @@ LL | ()
|
||||||
|
|
|
|
||||||
= note: expected type parameter `T`
|
= note: expected type parameter `T`
|
||||||
found unit type `()`
|
found unit type `()`
|
||||||
|
= note: the caller chooses a type for `T` which can be different from `()`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
21
tests/ui/return/return-ty-mismatch-note.rs
Normal file
21
tests/ui/return/return-ty-mismatch-note.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Checks existence of a note for "a caller chooses ty for ty param" upon return ty mismatch.
|
||||||
|
|
||||||
|
fn f<T>() -> (T,) {
|
||||||
|
(0,) //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g<U, V>() -> (U, V) {
|
||||||
|
(0, "foo")
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn h() -> u8 {
|
||||||
|
0u8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
f::<()>();
|
||||||
|
g::<(), ()>;
|
||||||
|
let _ = h();
|
||||||
|
}
|
36
tests/ui/return/return-ty-mismatch-note.stderr
Normal file
36
tests/ui/return/return-ty-mismatch-note.stderr
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/return-ty-mismatch-note.rs:4:6
|
||||||
|
|
|
||||||
|
LL | fn f<T>() -> (T,) {
|
||||||
|
| - expected this type parameter
|
||||||
|
LL | (0,)
|
||||||
|
| ^ expected type parameter `T`, found integer
|
||||||
|
|
|
||||||
|
= note: expected type parameter `T`
|
||||||
|
found type `{integer}`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/return-ty-mismatch-note.rs:8:6
|
||||||
|
|
|
||||||
|
LL | fn g<U, V>() -> (U, V) {
|
||||||
|
| - expected this type parameter
|
||||||
|
LL | (0, "foo")
|
||||||
|
| ^ expected type parameter `U`, found integer
|
||||||
|
|
|
||||||
|
= note: expected type parameter `U`
|
||||||
|
found type `{integer}`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/return-ty-mismatch-note.rs:8:9
|
||||||
|
|
|
||||||
|
LL | fn g<U, V>() -> (U, V) {
|
||||||
|
| - expected this type parameter
|
||||||
|
LL | (0, "foo")
|
||||||
|
| ^^^^^ expected type parameter `V`, found `&str`
|
||||||
|
|
|
||||||
|
= note: expected type parameter `V`
|
||||||
|
found reference `&'static str`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -10,6 +10,7 @@ LL | t.clone()
|
||||||
|
|
|
|
||||||
= note: expected type parameter `_`
|
= note: expected type parameter `_`
|
||||||
found reference `&_`
|
found reference `&_`
|
||||||
|
= note: the caller chooses a type for `T` which can be different from `&T`
|
||||||
note: `T` does not implement `Clone`, so `&T` was cloned instead
|
note: `T` does not implement `Clone`, so `&T` was cloned instead
|
||||||
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
|
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
|
||||||
|
|
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ LL | return a.bar();
|
||||||
|
|
|
|
||||||
= note: expected type parameter `B`
|
= note: expected type parameter `B`
|
||||||
found associated type `<A as MyTrait>::T`
|
found associated type `<A as MyTrait>::T`
|
||||||
|
= note: the caller chooses a type for `B` which can be different from `<A as MyTrait>::T`
|
||||||
help: consider further restricting this bound
|
help: consider further restricting this bound
|
||||||
|
|
|
|
||||||
LL | pub fn foo<A: MyTrait<T = B>, B>(a: A) -> B {
|
LL | pub fn foo<A: MyTrait<T = B>, B>(a: A) -> B {
|
||||||
|
|
34
tests/ui/transmute/transmute-zst-generics.rs
Normal file
34
tests/ui/transmute/transmute-zst-generics.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Transmuting to/from ZSTs that contain generics.
|
||||||
|
|
||||||
|
#![feature(transmute_generic_consts)]
|
||||||
|
|
||||||
|
// Verify non-generic ZST -> generic ZST transmute
|
||||||
|
unsafe fn cast_zst0<T>(from: ()) -> [T; 0] {
|
||||||
|
::std::mem::transmute::<(), [T; 0]>(from)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify generic ZST -> non-generic ZST transmute
|
||||||
|
unsafe fn cast_zst1<T>(from: [T; 0]) -> () {
|
||||||
|
::std::mem::transmute::<[T; 0], ()>(from)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify transmute with generic compound types
|
||||||
|
unsafe fn cast_zst2<T>(from: ()) -> [(T, T); 0] {
|
||||||
|
::std::mem::transmute::<(), [(T, T); 0]>(from)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify transmute with ZST propagation through arrays
|
||||||
|
unsafe fn cast_zst3<T>(from: ()) -> [[T; 0]; 8] {
|
||||||
|
::std::mem::transmute::<(), [[T; 0]; 8]>(from)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
unsafe {
|
||||||
|
let _: [u32; 0] = cast_zst0(());
|
||||||
|
let _ = cast_zst1::<u32>([]);
|
||||||
|
let _: [(u32, u32); 0] = cast_zst2(());
|
||||||
|
let _: [[u32; 0]; 8] = cast_zst3(());
|
||||||
|
};
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ LL | x
|
||||||
found type parameter `Foo`
|
found type parameter `Foo`
|
||||||
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
|
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||||
|
= note: the caller chooses a type for `Bar` which can be different from `Foo`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ LL | u
|
||||||
found type parameter `X`
|
found type parameter `X`
|
||||||
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
|
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
|
||||||
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||||
|
= note: the caller chooses a type for `Self` which can be different from `X`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ LL | self.iter()
|
||||||
|
|
|
|
||||||
= note: expected type parameter `I`
|
= note: expected type parameter `I`
|
||||||
found struct `std::slice::Iter<'_, N>`
|
found struct `std::slice::Iter<'_, N>`
|
||||||
|
= note: the caller chooses a type for `I` which can be different from `std::slice::Iter<'_, N>`
|
||||||
|
|
||||||
error[E0599]: no method named `iter` found for reference `&G` in the current scope
|
error[E0599]: no method named `iter` found for reference `&G` in the current scope
|
||||||
--> $DIR/issue-13853.rs:27:23
|
--> $DIR/issue-13853.rs:27:23
|
||||||
|
|
|
@ -623,7 +623,7 @@ cc = ["@davidtwco", "@compiler-errors", "@TaKO8Ki"]
|
||||||
|
|
||||||
[mentions."compiler/stable_mir"]
|
[mentions."compiler/stable_mir"]
|
||||||
message = "This PR changes Stable MIR"
|
message = "This PR changes Stable MIR"
|
||||||
cc = ["@oli-obk", "@celinval", "@spastorino", "@ouz-a"]
|
cc = ["@oli-obk", "@celinval", "@ouz-a"]
|
||||||
|
|
||||||
[mentions."compiler/rustc_target/src/spec"]
|
[mentions."compiler/rustc_target/src/spec"]
|
||||||
message = """
|
message = """
|
||||||
|
@ -833,6 +833,7 @@ parser = [
|
||||||
"@estebank",
|
"@estebank",
|
||||||
"@nnethercote",
|
"@nnethercote",
|
||||||
"@petrochenkov",
|
"@petrochenkov",
|
||||||
|
"@spastorino",
|
||||||
]
|
]
|
||||||
lexer = [
|
lexer = [
|
||||||
"@nnethercote",
|
"@nnethercote",
|
||||||
|
@ -841,6 +842,7 @@ lexer = [
|
||||||
]
|
]
|
||||||
arena = [
|
arena = [
|
||||||
"@nnethercote",
|
"@nnethercote",
|
||||||
|
"@spastorino",
|
||||||
]
|
]
|
||||||
mir = [
|
mir = [
|
||||||
"@davidtwco",
|
"@davidtwco",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue