mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 15:32:06 +00:00
Auto merge of #3395 - rust-lang:rustup-2024-03-23, r=saethlin
Automatic Rustup
This commit is contained in:
commit
f0d864fe04
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 Perry <james.austin.perry@gmail.com>
|
||||
James Sanderson <zofrex@gmail.com>
|
||||
Jan-Erik Rediger <janerik@fnordig.de> <badboy@archlinux.us>
|
||||
Jaro Fietz <jaro.fietz@gmx.de>
|
||||
Jason Fager <jfager@gmail.com>
|
||||
Jason Liquorish <jason@liquori.sh> <Bassetts@users.noreply.github.com>
|
||||
|
40
Cargo.lock
40
Cargo.lock
@ -214,7 +214,7 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9792d37ca5173d7e7f4fe453739a0671d0557915a030a383d6b866476bbc3e71"
|
||||
dependencies = [
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -281,7 +281,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
@ -2636,10 +2636,21 @@ dependencies = [
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
"ruzstd",
|
||||
"ruzstd 0.5.0",
|
||||
"wasmparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7090bae93f8585aad99e595b7073c5de9ba89fbd6b4e9f0cdd7a10177273ac8"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"memchr",
|
||||
"ruzstd 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "odht"
|
||||
version = "0.3.1"
|
||||
@ -3323,6 +3334,7 @@ dependencies = [
|
||||
name = "run_make_support"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"object 0.34.0",
|
||||
"wasmparser",
|
||||
]
|
||||
|
||||
@ -3634,7 +3646,7 @@ dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"libc",
|
||||
"measureme",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"rustc-demangle",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
@ -3670,7 +3682,7 @@ dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"pathdiff",
|
||||
"regex",
|
||||
"rustc_arena",
|
||||
@ -3686,6 +3698,7 @@ dependencies = [
|
||||
"rustc_macros",
|
||||
"rustc_metadata",
|
||||
"rustc_middle",
|
||||
"rustc_monomorphize",
|
||||
"rustc_query_system",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
@ -4630,7 +4643,7 @@ name = "rustc_target"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_feature",
|
||||
@ -4897,6 +4910,17 @@ dependencies = [
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruzstd"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"derive_more",
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.17"
|
||||
@ -5200,7 +5224,7 @@ dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"profiler_builtins",
|
||||
@ -5517,7 +5541,7 @@ checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
"hashbrown",
|
||||
"object",
|
||||
"object 0.32.2",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -66,15 +66,6 @@ exclude = [
|
||||
]
|
||||
|
||||
[profile.release.package.compiler_builtins]
|
||||
# The compiler-builtins crate cannot reference libcore, and its own CI will
|
||||
# verify that this is the case. This requires, however, that the crate is built
|
||||
# without overflow checks and debug assertions. Forcefully disable debug
|
||||
# assertions and overflow checks here which should ensure that even if these
|
||||
# assertions are enabled for libstd we won't enable them for compiler_builtins
|
||||
# which should ensure we still link everything correctly.
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
|
||||
# For compiler-builtins we always use a high number of codegen units.
|
||||
# The goal here is to place every single intrinsic into its own object
|
||||
# file to avoid symbol clashes with the system libgcc if possible. Note
|
||||
|
@ -366,7 +366,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
Some(variant.fields[field].name.to_string())
|
||||
}
|
||||
ty::Tuple(_) => Some(field.index().to_string()),
|
||||
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
|
||||
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
|
||||
self.describe_field_from_ty(ty, field, variant_index, including_tuple_field)
|
||||
}
|
||||
ty::Array(ty, _) | ty::Slice(ty) => {
|
||||
|
@ -503,10 +503,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
ty::VarianceDiagInfo::None => {}
|
||||
ty::VarianceDiagInfo::Invariant { ty, param_index } => {
|
||||
let (desc, note) = match ty.kind() {
|
||||
ty::RawPtr(ty_mut) => {
|
||||
assert_eq!(ty_mut.mutbl, rustc_hir::Mutability::Mut);
|
||||
ty::RawPtr(ty, mutbl) => {
|
||||
assert_eq!(*mutbl, rustc_hir::Mutability::Mut);
|
||||
(
|
||||
format!("a mutable pointer to `{}`", ty_mut.ty),
|
||||
format!("a mutable pointer to `{}`", ty),
|
||||
"mutable pointers are invariant over their type parameter".to_string(),
|
||||
)
|
||||
}
|
||||
|
@ -555,8 +555,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
search_stack.push((*elem_ty, elem_hir_ty));
|
||||
}
|
||||
|
||||
(ty::RawPtr(mut_ty), hir::TyKind::Ptr(mut_hir_ty)) => {
|
||||
search_stack.push((mut_ty.ty, &mut_hir_ty.ty));
|
||||
(ty::RawPtr(mut_ty, _), hir::TyKind::Ptr(mut_hir_ty)) => {
|
||||
search_stack.push((*mut_ty, &mut_hir_ty.ty));
|
||||
}
|
||||
|
||||
_ => {
|
||||
|
@ -1649,7 +1649,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(_)
|
||||
@ -2284,8 +2284,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::RawPtr(tnm) => {
|
||||
match tnm.mutbl {
|
||||
ty::RawPtr(_, mutbl) => {
|
||||
match mutbl {
|
||||
// `*const` raw pointers are not mutable
|
||||
hir::Mutability::Not => Err(place),
|
||||
// `*mut` raw pointers are always mutable, regardless of
|
||||
|
@ -2065,7 +2065,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
from_closure: constraint.from_closure,
|
||||
cause: ObligationCause::new(constraint.span, CRATE_DEF_ID, cause_code.clone()),
|
||||
variance_info: constraint.variance_info,
|
||||
outlives_constraint: *constraint,
|
||||
})
|
||||
.collect();
|
||||
debug!("categorized_path={:#?}", categorized_path);
|
||||
@ -2294,5 +2293,4 @@ pub struct BlameConstraint<'tcx> {
|
||||
pub from_closure: bool,
|
||||
pub cause: ObligationCause<'tcx>,
|
||||
pub variance_info: ty::VarianceDiagInfo<'tcx>,
|
||||
pub outlives_constraint: OutlivesConstraint<'tcx>,
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
) {
|
||||
self.prove_predicate(
|
||||
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,
|
||||
category,
|
||||
|
@ -2157,15 +2157,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
|
||||
let ty::RawPtr(ty::TypeAndMut { ty: ty_from, mutbl: hir::Mutability::Mut }) =
|
||||
op.ty(body, tcx).kind()
|
||||
let ty::RawPtr(ty_from, hir::Mutability::Mut) = op.ty(body, tcx).kind()
|
||||
else {
|
||||
span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
|
||||
return;
|
||||
};
|
||||
let ty::RawPtr(ty::TypeAndMut { ty: ty_to, mutbl: hir::Mutability::Not }) =
|
||||
ty.kind()
|
||||
else {
|
||||
let ty::RawPtr(ty_to, hir::Mutability::Not) = ty.kind() else {
|
||||
span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
|
||||
return;
|
||||
};
|
||||
@ -2190,12 +2187,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
let ty_from = op.ty(body, tcx);
|
||||
|
||||
let opt_ty_elem_mut = match ty_from.kind() {
|
||||
ty::RawPtr(ty::TypeAndMut { mutbl: array_mut, ty: array_ty }) => {
|
||||
match array_ty.kind() {
|
||||
ty::RawPtr(array_ty, array_mut) => match array_ty.kind() {
|
||||
ty::Array(ty_elem, _) => Some((ty_elem, *array_mut)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@ -2210,9 +2205,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
};
|
||||
|
||||
let (ty_to, ty_to_mut) = match ty.kind() {
|
||||
ty::RawPtr(ty::TypeAndMut { mutbl: ty_to_mut, ty: ty_to }) => {
|
||||
(ty_to, *ty_to_mut)
|
||||
}
|
||||
ty::RawPtr(ty_to, ty_to_mut) => (ty_to, *ty_to_mut),
|
||||
_ => {
|
||||
span_mirbug!(
|
||||
self,
|
||||
@ -2413,7 +2406,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
let ty_left = left.ty(body, tcx);
|
||||
match ty_left.kind() {
|
||||
// Types with regions are comparable if they have a common super-type.
|
||||
ty::RawPtr(_) | ty::FnPtr(_) => {
|
||||
ty::RawPtr(_, _) | ty::FnPtr(_) => {
|
||||
let ty_right = right.ty(body, tcx);
|
||||
let common_ty = self.infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
|
@ -51,7 +51,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
||||
|
||||
let (ident, vdata, fields) = match substr.fields {
|
||||
Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
|
||||
EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields),
|
||||
EnumMatching(_, v, fields) => (v.ident, &v.data, fields),
|
||||
AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, substr),
|
||||
EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
|
||||
cx.dcx().span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
|
||||
|
@ -226,7 +226,7 @@ fn encodable_substructure(
|
||||
BlockOrExpr::new_expr(expr)
|
||||
}
|
||||
|
||||
EnumMatching(idx, _, variant, fields) => {
|
||||
EnumMatching(idx, variant, fields) => {
|
||||
// We're not generating an AST that the borrow checker is expecting,
|
||||
// so we need to generate a unique local variable to take the
|
||||
// mutable loan out on, otherwise we get conflicts which don't
|
||||
|
@ -310,10 +310,10 @@ pub enum SubstructureFields<'a> {
|
||||
/// variants has any fields).
|
||||
AllFieldlessEnum(&'a ast::EnumDef),
|
||||
|
||||
/// Matching variants of the enum: variant index, variant count, ast::Variant,
|
||||
/// Matching variants of the enum: variant index, ast::Variant,
|
||||
/// fields: the field name is only non-`None` in the case of a struct
|
||||
/// variant.
|
||||
EnumMatching(usize, usize, &'a ast::Variant, Vec<FieldInfo>),
|
||||
EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo>),
|
||||
|
||||
/// The tag of an enum. The first field is a `FieldInfo` for the tags, as
|
||||
/// if they were fields. The second field is the expression to combine the
|
||||
@ -1272,7 +1272,7 @@ impl<'a> MethodDef<'a> {
|
||||
trait_,
|
||||
type_ident,
|
||||
nonselflike_args,
|
||||
&EnumMatching(0, 1, &variants[0], Vec::new()),
|
||||
&EnumMatching(0, &variants[0], Vec::new()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1318,7 +1318,7 @@ impl<'a> MethodDef<'a> {
|
||||
// expressions for referencing every field of every
|
||||
// Self arg, assuming all are instances of VariantK.
|
||||
// Build up code associated with such a case.
|
||||
let substructure = EnumMatching(index, variants.len(), variant, fields);
|
||||
let substructure = EnumMatching(index, variant, fields);
|
||||
let arm_expr = self
|
||||
.call_substructure_method(
|
||||
cx,
|
||||
@ -1346,7 +1346,7 @@ impl<'a> MethodDef<'a> {
|
||||
trait_,
|
||||
type_ident,
|
||||
nonselflike_args,
|
||||
&EnumMatching(0, variants.len(), v, Vec::new()),
|
||||
&EnumMatching(0, v, Vec::new()),
|
||||
)
|
||||
.into_expr(cx, span),
|
||||
)
|
||||
|
@ -8,8 +8,11 @@ use std::borrow::Cow;
|
||||
|
||||
use cranelift_codegen::ir::SigRef;
|
||||
use cranelift_module::ModuleError;
|
||||
use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::ty::layout::FnAbiOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::call::{Conv, FnAbi};
|
||||
@ -372,6 +375,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||
ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, fn_args)
|
||||
.polymorphize(fx.tcx);
|
||||
|
||||
if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) {
|
||||
if target.is_some() {
|
||||
let caller = with_no_trimmed_paths!(fx.tcx.def_path_str(fx.instance.def_id()));
|
||||
let callee = with_no_trimmed_paths!(fx.tcx.def_path_str(def_id));
|
||||
fx.tcx.dcx().emit_err(CompilerBuiltinsCannotCall { caller, callee });
|
||||
} else {
|
||||
fx.bcx.ins().trap(TrapCode::User(0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if fx.tcx.symbol_name(instance).name.starts_with("llvm.") {
|
||||
crate::intrinsics::codegen_llvm_intrinsic_call(
|
||||
fx,
|
||||
@ -663,11 +677,7 @@ pub(crate) fn codegen_drop<'tcx>(
|
||||
|
||||
let arg_value = drop_place.place_ref(
|
||||
fx,
|
||||
fx.layout_of(Ty::new_ref(
|
||||
fx.tcx,
|
||||
fx.tcx.lifetimes.re_erased,
|
||||
TypeAndMut { ty, mutbl: crate::rustc_hir::Mutability::Mut },
|
||||
)),
|
||||
fx.layout_of(Ty::new_mut_ref(fx.tcx, fx.tcx.lifetimes.re_erased, ty)),
|
||||
);
|
||||
let arg_value = adjust_arg_for_abi(fx, arg_value, &fn_abi.args[0], true);
|
||||
|
||||
|
@ -8,6 +8,7 @@ use rustc_index::IndexVec;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::layout::FnAbiOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
|
||||
use crate::constant::ConstantCx;
|
||||
use crate::debuginfo::FunctionDebugContext;
|
||||
@ -999,6 +1000,12 @@ fn codegen_panic_inner<'tcx>(
|
||||
let def_id = fx.tcx.require_lang_item(lang_item, span);
|
||||
|
||||
let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
|
||||
|
||||
if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) {
|
||||
fx.bcx.ins().trap(TrapCode::User(0));
|
||||
return;
|
||||
}
|
||||
|
||||
let symbol_name = fx.tcx.symbol_name(instance).name;
|
||||
|
||||
fx.lib_call(
|
||||
|
@ -69,7 +69,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ
|
||||
FloatTy::F128 => unimplemented!("f16_f128"),
|
||||
},
|
||||
ty::FnPtr(_) => pointer_ty(tcx),
|
||||
ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => {
|
||||
ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => {
|
||||
if has_ptr_meta(tcx, *pointee_ty) {
|
||||
return None;
|
||||
} else {
|
||||
@ -89,7 +89,7 @@ fn clif_pair_type_from_ty<'tcx>(
|
||||
ty::Tuple(types) if types.len() == 2 => {
|
||||
(clif_type_from_ty(tcx, types[0])?, clif_type_from_ty(tcx, types[1])?)
|
||||
}
|
||||
ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => {
|
||||
ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => {
|
||||
if has_ptr_meta(tcx, *pointee_ty) {
|
||||
(pointer_ty(tcx), pointer_ty(tcx))
|
||||
} else {
|
||||
|
@ -21,6 +21,7 @@ extern crate rustc_hir;
|
||||
extern crate rustc_incremental;
|
||||
extern crate rustc_index;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_monomorphize;
|
||||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
extern crate rustc_target;
|
||||
|
@ -70,10 +70,8 @@ fn unsize_ptr<'tcx>(
|
||||
) -> (Value, Value) {
|
||||
match (&src_layout.ty.kind(), &dst_layout.ty.kind()) {
|
||||
(&ty::Ref(_, a, _), &ty::Ref(_, b, _))
|
||||
| (&ty::Ref(_, a, _), &ty::RawPtr(ty::TypeAndMut { ty: b, .. }))
|
||||
| (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
|
||||
(src, unsized_info(fx, *a, *b, old_info))
|
||||
}
|
||||
| (&ty::Ref(_, a, _), &ty::RawPtr(b, _))
|
||||
| (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => (src, unsized_info(fx, *a, *b, old_info)),
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
|
||||
assert_eq!(def_a, def_b);
|
||||
|
||||
|
@ -865,15 +865,10 @@ pub(crate) fn assert_assignable<'tcx>(
|
||||
return;
|
||||
}
|
||||
match (from_ty.kind(), to_ty.kind()) {
|
||||
(ty::Ref(_, a, _), ty::Ref(_, b, _))
|
||||
| (
|
||||
ty::RawPtr(TypeAndMut { ty: a, mutbl: _ }),
|
||||
ty::RawPtr(TypeAndMut { ty: b, mutbl: _ }),
|
||||
) => {
|
||||
(ty::Ref(_, a, _), ty::Ref(_, b, _)) | (ty::RawPtr(a, _), ty::RawPtr(b, _)) => {
|
||||
assert_assignable(fx, *a, *b, limit - 1);
|
||||
}
|
||||
(ty::Ref(_, a, _), ty::RawPtr(TypeAndMut { ty: b, mutbl: _ }))
|
||||
| (ty::RawPtr(TypeAndMut { ty: a, mutbl: _ }), ty::Ref(_, b, _)) => {
|
||||
(ty::Ref(_, a, _), ty::RawPtr(b, _)) | (ty::RawPtr(a, _), ty::Ref(_, b, _)) => {
|
||||
assert_assignable(fx, *a, *b, limit - 1);
|
||||
}
|
||||
(ty::FnPtr(_), ty::FnPtr(_)) => {
|
||||
|
@ -110,6 +110,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
||||
local_gen_sym_counter: Cell<usize>,
|
||||
|
||||
eh_personality: Cell<Option<RValue<'gcc>>>,
|
||||
#[cfg(feature="master")]
|
||||
pub rust_try_fn: Cell<Option<(Type<'gcc>, Function<'gcc>)>>,
|
||||
|
||||
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
|
||||
@ -121,6 +122,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
||||
/// FIXME(antoyo): fix the rustc API to avoid having this hack.
|
||||
pub structs_as_pointer: RefCell<FxHashSet<RValue<'gcc>>>,
|
||||
|
||||
#[cfg(feature="master")]
|
||||
pub cleanup_blocks: RefCell<FxHashSet<Block<'gcc>>>,
|
||||
}
|
||||
|
||||
@ -325,9 +327,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
struct_types: Default::default(),
|
||||
local_gen_sym_counter: Cell::new(0),
|
||||
eh_personality: Cell::new(None),
|
||||
#[cfg(feature="master")]
|
||||
rust_try_fn: Cell::new(None),
|
||||
pointee_infos: Default::default(),
|
||||
structs_as_pointer: Default::default(),
|
||||
#[cfg(feature="master")]
|
||||
cleanup_blocks: Default::default(),
|
||||
};
|
||||
// TODO(antoyo): instead of doing this, add SsizeT to libgccjit.
|
||||
|
@ -796,16 +796,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
|
||||
// This counts how many pointers
|
||||
fn ptr_count(t: Ty<'_>) -> usize {
|
||||
match t.kind() {
|
||||
ty::RawPtr(p) => 1 + ptr_count(p.ty),
|
||||
match *t.kind() {
|
||||
ty::RawPtr(p_ty, _) => 1 + ptr_count(p_ty),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Non-ptr type
|
||||
fn non_ptr(t: Ty<'_>) -> Ty<'_> {
|
||||
match t.kind() {
|
||||
ty::RawPtr(p) => non_ptr(p.ty),
|
||||
match *t.kind() {
|
||||
ty::RawPtr(p_ty, _) => non_ptr(p_ty),
|
||||
_ => t,
|
||||
}
|
||||
}
|
||||
@ -814,8 +814,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
// to the element type of the first argument
|
||||
let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx());
|
||||
let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (pointer_count, underlying_ty) = match element_ty1.kind() {
|
||||
ty::RawPtr(p) if p.ty == in_elem => (ptr_count(element_ty1), non_ptr(element_ty1)),
|
||||
let (pointer_count, underlying_ty) = match *element_ty1.kind() {
|
||||
ty::RawPtr(p_ty, _) if p_ty == in_elem => (ptr_count(element_ty1), non_ptr(element_ty1)),
|
||||
_ => {
|
||||
require!(
|
||||
false,
|
||||
@ -910,16 +910,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
|
||||
// This counts how many pointers
|
||||
fn ptr_count(t: Ty<'_>) -> usize {
|
||||
match t.kind() {
|
||||
ty::RawPtr(p) => 1 + ptr_count(p.ty),
|
||||
match *t.kind() {
|
||||
ty::RawPtr(p_ty, _) => 1 + ptr_count(p_ty),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Non-ptr type
|
||||
fn non_ptr(t: Ty<'_>) -> Ty<'_> {
|
||||
match t.kind() {
|
||||
ty::RawPtr(p) => non_ptr(p.ty),
|
||||
match *t.kind() {
|
||||
ty::RawPtr(p_ty, _) => non_ptr(p_ty),
|
||||
_ => t,
|
||||
}
|
||||
}
|
||||
@ -929,8 +929,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx());
|
||||
let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
let (pointer_count, underlying_ty) = match element_ty1.kind() {
|
||||
ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mut => {
|
||||
let (pointer_count, underlying_ty) = match *element_ty1.kind() {
|
||||
ty::RawPtr(p_ty, mutbl) if p_ty == in_elem && mutbl == hir::Mutability::Mut => {
|
||||
(ptr_count(element_ty1), non_ptr(element_ty1))
|
||||
}
|
||||
_ => {
|
||||
|
@ -27,9 +27,7 @@ use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{
|
||||
call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
|
||||
};
|
||||
use rustc_target::abi::{call::FnAbi, HasDataLayout, TargetDataLayout, VariantIdx};
|
||||
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
@ -83,7 +81,6 @@ pub struct CodegenCx<'ll, 'tcx> {
|
||||
/// Mapping of scalar types to llvm types.
|
||||
pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'ll Type>>,
|
||||
|
||||
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
|
||||
pub isize_ty: &'ll Type,
|
||||
|
||||
pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'ll, 'tcx>>,
|
||||
@ -450,7 +447,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||
compiler_used_statics: RefCell::new(Vec::new()),
|
||||
type_lowering: Default::default(),
|
||||
scalar_lltypes: Default::default(),
|
||||
pointee_infos: Default::default(),
|
||||
isize_ty,
|
||||
coverage_cx,
|
||||
dbg_cx,
|
||||
|
@ -452,7 +452,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
|
||||
ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id),
|
||||
ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id),
|
||||
ty::Foreign(..) => build_foreign_type_di_node(cx, t, unique_type_id),
|
||||
ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => {
|
||||
ty::RawPtr(pointee_type, _) | ty::Ref(_, pointee_type, _) => {
|
||||
build_pointer_or_reference_di_node(cx, t, pointee_type, unique_type_id)
|
||||
}
|
||||
// Some `Box` are newtyped pointers, make debuginfo aware of that.
|
||||
|
@ -1483,7 +1483,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
v.normalize(bx.target_spec().pointer_width).bit_width().unwrap()
|
||||
),
|
||||
ty::Float(v) => format!("v{}f{}", vec_len, v.bit_width()),
|
||||
ty::RawPtr(_) => format!("v{}p0", vec_len),
|
||||
ty::RawPtr(_, _) => format!("v{}p0", vec_len),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -1493,7 +1493,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
ty::Int(v) => cx.type_int_from_ty(v),
|
||||
ty::Uint(v) => cx.type_uint_from_ty(v),
|
||||
ty::Float(v) => cx.type_float_from_ty(v),
|
||||
ty::RawPtr(_) => cx.type_ptr(),
|
||||
ty::RawPtr(_, _) => cx.type_ptr(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
cx.type_vector(elem_ty, vec_len)
|
||||
@ -1548,8 +1548,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
|
||||
require!(
|
||||
matches!(
|
||||
element_ty1.kind(),
|
||||
ty::RawPtr(p) if p.ty == in_elem && p.ty.kind() == element_ty0.kind()
|
||||
*element_ty1.kind(),
|
||||
ty::RawPtr(p_ty, _) if p_ty == in_elem && p_ty.kind() == element_ty0.kind()
|
||||
),
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
@ -1654,8 +1654,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
|
||||
require!(
|
||||
matches!(
|
||||
pointer_ty.kind(),
|
||||
ty::RawPtr(p) if p.ty == values_elem && p.ty.kind() == values_elem.kind()
|
||||
*pointer_ty.kind(),
|
||||
ty::RawPtr(p_ty, _) if p_ty == values_elem && p_ty.kind() == values_elem.kind()
|
||||
),
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
@ -1746,8 +1746,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
// The second argument must be a mutable pointer type matching the element type
|
||||
require!(
|
||||
matches!(
|
||||
pointer_ty.kind(),
|
||||
ty::RawPtr(p) if p.ty == values_elem && p.ty.kind() == values_elem.kind() && p.mutbl.is_mut()
|
||||
*pointer_ty.kind(),
|
||||
ty::RawPtr(p_ty, p_mutbl) if p_ty == values_elem && p_ty.kind() == values_elem.kind() && p_mutbl.is_mut()
|
||||
),
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
@ -1843,9 +1843,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
|
||||
require!(
|
||||
matches!(
|
||||
element_ty1.kind(),
|
||||
ty::RawPtr(p)
|
||||
if p.ty == in_elem && p.mutbl.is_mut() && p.ty.kind() == element_ty0.kind()
|
||||
*element_ty1.kind(),
|
||||
ty::RawPtr(p_ty, p_mutbl)
|
||||
if p_ty == in_elem && p_mutbl.is_mut() && p_ty.kind() == element_ty0.kind()
|
||||
),
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
@ -2074,8 +2074,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
);
|
||||
|
||||
match in_elem.kind() {
|
||||
ty::RawPtr(p) => {
|
||||
let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
ty::RawPtr(p_ty, _) => {
|
||||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(
|
||||
@ -2088,8 +2088,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
}
|
||||
}
|
||||
match out_elem.kind() {
|
||||
ty::RawPtr(p) => {
|
||||
let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
ty::RawPtr(p_ty, _) => {
|
||||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(
|
||||
@ -2120,7 +2120,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
);
|
||||
|
||||
match in_elem.kind() {
|
||||
ty::RawPtr(_) => {}
|
||||
ty::RawPtr(_, _) => {}
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem })
|
||||
}
|
||||
@ -2152,7 +2152,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
_ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: in_elem }),
|
||||
}
|
||||
match out_elem.kind() {
|
||||
ty::RawPtr(_) => {}
|
||||
ty::RawPtr(_, _) => {}
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem })
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ rustc_index = { path = "../rustc_index" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_metadata = { path = "../rustc_metadata" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_monomorphize = { path = "../rustc_monomorphize" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
|
@ -16,6 +16,9 @@ codegen_ssa_cgu_not_recorded =
|
||||
|
||||
codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
|
||||
|
||||
codegen_ssa_compiler_builtins_cannot_call =
|
||||
`compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from `{$caller}` to `{$callee}`
|
||||
|
||||
codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error}
|
||||
|
||||
codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error}
|
||||
|
@ -193,8 +193,8 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
) -> (Bx::Value, Bx::Value) {
|
||||
debug!("unsize_ptr: {:?} => {:?}", src_ty, dst_ty);
|
||||
match (src_ty.kind(), dst_ty.kind()) {
|
||||
(&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(ty::TypeAndMut { ty: b, .. }))
|
||||
| (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
|
||||
(&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _))
|
||||
| (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => {
|
||||
assert_eq!(bx.cx().type_is_sized(a), old_info.is_none());
|
||||
(src, unsized_info(bx, a, b, old_info))
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
||||
@ -120,11 +121,11 @@ pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &Bx,
|
||||
span: Option<Span>,
|
||||
li: LangItem,
|
||||
) -> (Bx::FnAbiOfResult, Bx::Value) {
|
||||
) -> (Bx::FnAbiOfResult, Bx::Value, Instance<'tcx>) {
|
||||
let tcx = bx.tcx();
|
||||
let def_id = tcx.require_lang_item(li, span);
|
||||
let instance = ty::Instance::mono(tcx, def_id);
|
||||
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance))
|
||||
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance), instance)
|
||||
}
|
||||
|
||||
// To avoid UB from LLVM, these two functions mask RHS with an
|
||||
|
@ -138,7 +138,7 @@ fn push_debuginfo_type_name<'tcx>(
|
||||
output.push(')');
|
||||
}
|
||||
}
|
||||
ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
|
||||
ty::RawPtr(inner_type, mutbl) => {
|
||||
if cpp_like_debuginfo {
|
||||
match mutbl {
|
||||
Mutability::Not => output.push_str("ptr_const$<"),
|
||||
|
@ -1030,3 +1030,10 @@ pub struct FailedToGetLayout<'tcx> {
|
||||
pub struct ErrorCreatingRemarkDir {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_compiler_builtins_cannot_call)]
|
||||
pub struct CompilerBuiltinsCannotCall {
|
||||
pub caller: String,
|
||||
pub callee: String,
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ use super::{CachedLlbb, FunctionCx, LocalRef};
|
||||
|
||||
use crate::base;
|
||||
use crate::common::{self, IntPredicate};
|
||||
use crate::errors::CompilerBuiltinsCannotCall;
|
||||
use crate::meth;
|
||||
use crate::traits::*;
|
||||
use crate::MemFlags;
|
||||
@ -16,6 +17,7 @@ use rustc_middle::mir::{self, AssertKind, BasicBlock, SwitchTargets, UnwindTermi
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_span::{source_map::Spanned, sym, Span};
|
||||
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
|
||||
@ -157,8 +159,28 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
||||
destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
|
||||
mut unwind: mir::UnwindAction,
|
||||
copied_constant_arguments: &[PlaceRef<'tcx, <Bx as BackendTypes>::Value>],
|
||||
instance: Option<Instance<'tcx>>,
|
||||
mergeable_succ: bool,
|
||||
) -> MergingSucc {
|
||||
let tcx = bx.tcx();
|
||||
if let Some(instance) = instance {
|
||||
if is_call_from_compiler_builtins_to_upstream_monomorphization(tcx, instance) {
|
||||
if destination.is_some() {
|
||||
let caller = with_no_trimmed_paths!(tcx.def_path_str(fx.instance.def_id()));
|
||||
let callee = with_no_trimmed_paths!(tcx.def_path_str(instance.def_id()));
|
||||
tcx.dcx().emit_err(CompilerBuiltinsCannotCall { caller, callee });
|
||||
} else {
|
||||
info!(
|
||||
"compiler_builtins call to diverging function {:?} replaced with abort",
|
||||
instance.def_id()
|
||||
);
|
||||
bx.abort();
|
||||
bx.unreachable();
|
||||
return MergingSucc::False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is a cleanup block and the function we're calling can unwind, then
|
||||
// do an invoke, otherwise do a call.
|
||||
let fn_ty = bx.fn_decl_backend_type(fn_abi);
|
||||
@ -480,6 +502,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
let ty = location.ty(self.mir, bx.tcx()).ty;
|
||||
let ty = self.monomorphize(ty);
|
||||
let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
|
||||
let instance = drop_fn.clone();
|
||||
|
||||
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
|
||||
// we don't actually need to drop anything.
|
||||
@ -582,6 +605,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
Some((ReturnDest::Nothing, target)),
|
||||
unwind,
|
||||
&[],
|
||||
Some(instance),
|
||||
mergeable_succ,
|
||||
)
|
||||
}
|
||||
@ -658,10 +682,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
}
|
||||
};
|
||||
|
||||
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), lang_item);
|
||||
let (fn_abi, llfn, instance) = common::build_langcall(bx, Some(span), lang_item);
|
||||
|
||||
// Codegen the actual panic invoke/call.
|
||||
let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], false);
|
||||
let merging_succ =
|
||||
helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], Some(instance), false);
|
||||
assert_eq!(merging_succ, MergingSucc::False);
|
||||
MergingSucc::False
|
||||
}
|
||||
@ -677,7 +702,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
self.set_debug_loc(bx, terminator.source_info);
|
||||
|
||||
// Obtain the panic entry point.
|
||||
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), reason.lang_item());
|
||||
let (fn_abi, llfn, instance) = common::build_langcall(bx, Some(span), reason.lang_item());
|
||||
|
||||
// Codegen the actual panic invoke/call.
|
||||
let merging_succ = helper.do_call(
|
||||
@ -689,6 +714,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
None,
|
||||
mir::UnwindAction::Unreachable,
|
||||
&[],
|
||||
Some(instance),
|
||||
false,
|
||||
);
|
||||
assert_eq!(merging_succ, MergingSucc::False);
|
||||
@ -738,7 +764,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
let msg = bx.const_str(&msg_str);
|
||||
|
||||
// Obtain the panic entry point.
|
||||
let (fn_abi, llfn) =
|
||||
let (fn_abi, llfn, instance) =
|
||||
common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
|
||||
|
||||
// Codegen the actual panic invoke/call.
|
||||
@ -751,6 +777,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
|
||||
unwind,
|
||||
&[],
|
||||
Some(instance),
|
||||
mergeable_succ,
|
||||
)
|
||||
} else {
|
||||
@ -798,6 +825,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
ty::FnPtr(_) => (None, Some(callee.immediate())),
|
||||
_ => bug!("{} is not callable", callee.layout.ty),
|
||||
};
|
||||
|
||||
let def = instance.map(|i| i.def);
|
||||
|
||||
if let Some(ty::InstanceDef::DropGlue(_, None)) = def {
|
||||
@ -1106,6 +1134,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
destination,
|
||||
unwind,
|
||||
&copied_constant_arguments,
|
||||
instance,
|
||||
mergeable_succ,
|
||||
)
|
||||
}
|
||||
@ -1664,11 +1693,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
||||
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
|
||||
|
||||
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item());
|
||||
let (fn_abi, fn_ptr, instance) = common::build_langcall(&bx, None, reason.lang_item());
|
||||
if is_call_from_compiler_builtins_to_upstream_monomorphization(bx.tcx(), instance) {
|
||||
bx.abort();
|
||||
} else {
|
||||
let fn_ty = bx.fn_decl_backend_type(fn_abi);
|
||||
|
||||
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref());
|
||||
bx.apply_attrs_to_cleanup_callsite(llret);
|
||||
}
|
||||
|
||||
bx.unreachable();
|
||||
|
||||
|
@ -414,10 +414,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
calculate_debuginfo_offset(bx, var.projection, base);
|
||||
|
||||
// Create a variable which will be a pointer to the actual value
|
||||
let ptr_ty = Ty::new_ptr(
|
||||
bx.tcx(),
|
||||
ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty },
|
||||
);
|
||||
let ptr_ty = Ty::new_mut_ptr(bx.tcx(), place.layout.ty);
|
||||
let ptr_layout = bx.layout_of(ptr_ty);
|
||||
let alloca = PlaceRef::alloca(bx, ptr_layout);
|
||||
bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
|
||||
|
@ -572,20 +572,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
||||
mir::Rvalue::Ref(_, bk, place) => {
|
||||
let mk_ref = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| {
|
||||
Ty::new_ref(
|
||||
tcx,
|
||||
tcx.lifetimes.re_erased,
|
||||
ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() },
|
||||
)
|
||||
Ty::new_ref(tcx, tcx.lifetimes.re_erased, ty, bk.to_mutbl_lossy())
|
||||
};
|
||||
self.codegen_place_to_pointer(bx, place, mk_ref)
|
||||
}
|
||||
|
||||
mir::Rvalue::CopyForDeref(place) => self.codegen_operand(bx, &Operand::Copy(place)),
|
||||
mir::Rvalue::AddressOf(mutability, place) => {
|
||||
let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| {
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty, mutbl: mutability })
|
||||
};
|
||||
let mk_ptr =
|
||||
move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| Ty::new_ptr(tcx, ty, mutability);
|
||||
self.codegen_place_to_pointer(bx, place, mk_ptr)
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,8 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
let msg = bx.const_str(&msg_str);
|
||||
|
||||
// Obtain the panic entry point.
|
||||
let (fn_abi, llfn) = common::build_langcall(bx, None, LangItem::PanicNounwind);
|
||||
let (fn_abi, llfn, _instance) =
|
||||
common::build_langcall(bx, None, LangItem::PanicNounwind);
|
||||
|
||||
// Generate the call.
|
||||
// Cannot use `do_call` since we don't have a MIR terminator so we can't create a `TerminationCodegenHelper`.
|
||||
|
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_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
|
||||
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::ty::layout::LayoutOf;
|
||||
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)
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
pub fn eval_to_const_value_raw_provider<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -7,12 +7,14 @@ use rustc_middle::ty::{self, Ty};
|
||||
|
||||
use crate::interpret::format_interp_error;
|
||||
|
||||
mod dummy_machine;
|
||||
mod error;
|
||||
mod eval_queries;
|
||||
mod fn_queries;
|
||||
mod machine;
|
||||
mod valtrees;
|
||||
|
||||
pub use dummy_machine::*;
|
||||
pub use error::*;
|
||||
pub use eval_queries::*;
|
||||
pub use fn_queries::*;
|
||||
|
@ -98,7 +98,7 @@ fn const_to_valtree_inner<'tcx>(
|
||||
Ok(ty::ValTree::Leaf(val.assert_int()))
|
||||
}
|
||||
|
||||
ty::RawPtr(_) => {
|
||||
ty::RawPtr(_, _) => {
|
||||
// Not all raw pointers are allowed, as we cannot properly test them for
|
||||
// equality at compile-time (see `ptr_guaranteed_cmp`).
|
||||
// However we allow those that are just integers in disguise.
|
||||
@ -278,7 +278,7 @@ pub fn valtree_to_const_value<'tcx>(
|
||||
assert!(valtree.unwrap_branch().is_empty());
|
||||
mir::ConstValue::ZeroSized
|
||||
}
|
||||
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char | ty::RawPtr(_) => {
|
||||
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char | ty::RawPtr(_, _) => {
|
||||
match valtree {
|
||||
ty::ValTree::Leaf(scalar_int) => mir::ConstValue::Scalar(Scalar::Int(scalar_int)),
|
||||
ty::ValTree::Branch(_) => bug!(
|
||||
|
@ -6,7 +6,7 @@ use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
|
||||
use rustc_middle::mir::CastKind;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut};
|
||||
use rustc_middle::ty::{self, FloatTy, Ty};
|
||||
use rustc_target::abi::Integer;
|
||||
use rustc_type_ir::TyKind::*;
|
||||
|
||||
@ -230,7 +230,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
src: &ImmTy<'tcx, M::Provenance>,
|
||||
cast_to: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
|
||||
assert_matches!(src.layout.ty.kind(), ty::RawPtr(_) | ty::FnPtr(_));
|
||||
assert_matches!(src.layout.ty.kind(), ty::RawPtr(_, _) | ty::FnPtr(_));
|
||||
assert!(cast_to.ty.is_integral());
|
||||
|
||||
let scalar = src.to_scalar();
|
||||
@ -248,7 +248,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
cast_to: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
|
||||
assert!(src.layout.ty.is_integral());
|
||||
assert_matches!(cast_to.ty.kind(), ty::RawPtr(_));
|
||||
assert_matches!(cast_to.ty.kind(), ty::RawPtr(_, _));
|
||||
|
||||
// First cast to usize.
|
||||
let scalar = src.to_scalar();
|
||||
@ -435,10 +435,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
) -> InterpResult<'tcx> {
|
||||
trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty);
|
||||
match (&src.layout.ty.kind(), &cast_ty.ty.kind()) {
|
||||
(&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(TypeAndMut { ty: c, .. }))
|
||||
| (&ty::RawPtr(TypeAndMut { ty: s, .. }), &ty::RawPtr(TypeAndMut { ty: c, .. })) => {
|
||||
self.unsize_into_ptr(src, dest, *s, *c)
|
||||
}
|
||||
(&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(c, _))
|
||||
| (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, *s, *c),
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
|
||||
assert_eq!(def_a, def_b); // implies same number of fields
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use rustc_middle::mir;
|
||||
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::{VariantIdx, Variants};
|
||||
|
||||
@ -28,79 +28,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
throw_ub!(UninhabitedEnumVariantWritten(variant_index))
|
||||
}
|
||||
|
||||
match dest.layout().variants {
|
||||
abi::Variants::Single { index } => {
|
||||
assert_eq!(index, variant_index);
|
||||
}
|
||||
abi::Variants::Multiple {
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
tag: tag_layout,
|
||||
tag_field,
|
||||
..
|
||||
} => {
|
||||
match self.tag_for_variant(dest.layout().ty, variant_index)? {
|
||||
Some((tag, tag_field)) => {
|
||||
// No need to validate that the discriminant here because the
|
||||
// `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);
|
||||
|
||||
// `TyAndLayout::for_variant()` call earlier already checks the
|
||||
// variant is valid.
|
||||
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 {
|
||||
tag_encoding:
|
||||
TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
|
||||
tag: tag_layout,
|
||||
tag_field,
|
||||
..
|
||||
} => {
|
||||
// No need to validate that the discriminant here because the
|
||||
// `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
|
||||
|
||||
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...
|
||||
None => {
|
||||
// No need to write the tag here, because an untagged variant is
|
||||
// implicitly encoded. For `Niche`-optimized enums, it's by
|
||||
// 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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read discriminant, return the runtime value as well as the variant index.
|
||||
/// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
|
||||
@ -277,4 +226,77 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
};
|
||||
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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(_)
|
||||
|
@ -375,7 +375,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// We cannot use `builtin_deref` here since we need to reject `Box<T, MyAlloc>`.
|
||||
Ok(Some(match ty.kind() {
|
||||
ty::Ref(_, ty, _) => *ty,
|
||||
ty::RawPtr(mt) => mt.ty,
|
||||
ty::RawPtr(ty, _) => *ty,
|
||||
// We only accept `Box` with the default allocator.
|
||||
_ if ty.is_box_global(*self.tcx) => ty.boxed_ty(),
|
||||
_ => return Ok(None),
|
||||
|
@ -40,6 +40,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub fn provide(providers: &mut 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_allocation_raw = const_eval::eval_to_allocation_raw_provider;
|
||||
providers.eval_static_initializer = const_eval::eval_static_initializer_provider;
|
||||
|
@ -33,7 +33,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(_, _, _)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Never
|
||||
|
@ -42,7 +42,7 @@ impl<'tcx> Bounds<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
span: Span,
|
||||
polarity: ty::ImplPolarity,
|
||||
polarity: ty::PredicatePolarity,
|
||||
) {
|
||||
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
||||
}
|
||||
@ -52,7 +52,7 @@ impl<'tcx> Bounds<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
span: Span,
|
||||
polarity: ty::ImplPolarity,
|
||||
polarity: ty::PredicatePolarity,
|
||||
) {
|
||||
self.clauses.push((
|
||||
trait_ref
|
||||
|
@ -499,7 +499,7 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
|
||||
fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
|
||||
if match tcx.type_of(def_id).instantiate_identity().kind() {
|
||||
ty::RawPtr(_) => false,
|
||||
ty::RawPtr(_, _) => false,
|
||||
ty::Adt(adt_def, args) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *args),
|
||||
_ => true,
|
||||
} {
|
||||
@ -934,10 +934,13 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
|
||||
// No: char, "fat" pointers, compound types
|
||||
match e.kind() {
|
||||
ty::Param(_) => (), // pass struct<T>(T, T, T, T) through, let monomorphization catch errors
|
||||
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok
|
||||
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct(u8, u8, u8, u8) is ok
|
||||
ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct<T>([T; N]) through, let monomorphization catch errors
|
||||
ty::Array(t, _clen)
|
||||
if matches!(t.kind(), ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_)) =>
|
||||
if matches!(
|
||||
t.kind(),
|
||||
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _)
|
||||
) =>
|
||||
{ /* struct([f32; 4]) is ok */ }
|
||||
_ => {
|
||||
struct_span_code_err!(
|
||||
|
@ -191,7 +191,7 @@ pub fn check_intrinsic_type(
|
||||
ty::BoundRegion { var: ty::BoundVar::from_u32(2), kind: ty::BrEnv },
|
||||
);
|
||||
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
|
||||
(Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
|
||||
(Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
|
||||
})
|
||||
};
|
||||
|
||||
@ -240,15 +240,9 @@ pub fn check_intrinsic_type(
|
||||
sym::prefetch_read_data
|
||||
| sym::prefetch_write_data
|
||||
| sym::prefetch_read_instruction
|
||||
| sym::prefetch_write_instruction => (
|
||||
1,
|
||||
0,
|
||||
vec![
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
||||
tcx.types.i32,
|
||||
],
|
||||
Ty::new_unit(tcx),
|
||||
),
|
||||
| sym::prefetch_write_instruction => {
|
||||
(1, 0, vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.i32], Ty::new_unit(tcx))
|
||||
}
|
||||
sym::needs_drop => (1, 0, vec![], tcx.types.bool),
|
||||
|
||||
sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)),
|
||||
@ -257,28 +251,22 @@ pub fn check_intrinsic_type(
|
||||
sym::arith_offset => (
|
||||
1,
|
||||
0,
|
||||
vec![
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
||||
tcx.types.isize,
|
||||
],
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
||||
vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.isize],
|
||||
Ty::new_imm_ptr(tcx, param(0)),
|
||||
),
|
||||
sym::ptr_mask => (
|
||||
1,
|
||||
0,
|
||||
vec![
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
||||
tcx.types.usize,
|
||||
],
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
||||
vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.usize],
|
||||
Ty::new_imm_ptr(tcx, param(0)),
|
||||
),
|
||||
|
||||
sym::copy | sym::copy_nonoverlapping => (
|
||||
1,
|
||||
0,
|
||||
vec![
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
|
||||
Ty::new_imm_ptr(tcx, param(0)),
|
||||
Ty::new_mut_ptr(tcx, param(0)),
|
||||
tcx.types.usize,
|
||||
],
|
||||
Ty::new_unit(tcx),
|
||||
@ -287,8 +275,8 @@ pub fn check_intrinsic_type(
|
||||
1,
|
||||
0,
|
||||
vec![
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
||||
Ty::new_mut_ptr(tcx, param(0)),
|
||||
Ty::new_imm_ptr(tcx, param(0)),
|
||||
tcx.types.usize,
|
||||
],
|
||||
Ty::new_unit(tcx),
|
||||
@ -300,11 +288,7 @@ pub fn check_intrinsic_type(
|
||||
sym::write_bytes | sym::volatile_set_memory => (
|
||||
1,
|
||||
0,
|
||||
vec![
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
|
||||
tcx.types.u8,
|
||||
tcx.types.usize,
|
||||
],
|
||||
vec![Ty::new_mut_ptr(tcx, param(0)), tcx.types.u8, tcx.types.usize],
|
||||
Ty::new_unit(tcx),
|
||||
),
|
||||
|
||||
|
@ -62,9 +62,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
||||
ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
|
||||
ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
|
||||
ty::FnPtr(_) => Some(asm_ty_isize),
|
||||
ty::RawPtr(ty::TypeAndMut { ty, mutbl: _ }) if self.is_thin_ptr_ty(ty) => {
|
||||
Some(asm_ty_isize)
|
||||
}
|
||||
ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize),
|
||||
ty::Adt(adt, args) if adt.repr().simd() => {
|
||||
let fields = &adt.non_enum_variant().fields;
|
||||
let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, args);
|
||||
|
@ -954,7 +954,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
||||
hir_ty.span,
|
||||
"using function pointers as const generic parameters is forbidden",
|
||||
),
|
||||
ty::RawPtr(_) => tcx.dcx().struct_span_err(
|
||||
ty::RawPtr(_, _) => tcx.dcx().struct_span_err(
|
||||
hir_ty.span,
|
||||
"using raw pointers as const generic parameters is forbidden",
|
||||
),
|
||||
@ -1322,7 +1322,7 @@ fn check_impl<'tcx>(
|
||||
trait_ref,
|
||||
);
|
||||
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(
|
||||
wfcx.infcx,
|
||||
wfcx.param_env,
|
||||
|
@ -195,7 +195,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
(&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => Ok(()),
|
||||
(&RawPtr(_, a_mutbl), &RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
|
||||
(&Adt(def_a, args_a), &Adt(def_b, args_b)) if def_a.is_struct() && def_b.is_struct() => {
|
||||
if def_a != def_b {
|
||||
let source_path = tcx.def_path_str(def_a.did());
|
||||
@ -351,14 +351,17 @@ pub fn coerce_unsized_info<'tcx>(
|
||||
check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
|
||||
}
|
||||
|
||||
(&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(mt_b)) => {
|
||||
let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
|
||||
check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
|
||||
}
|
||||
(&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => check_mutbl(
|
||||
ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a },
|
||||
ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b },
|
||||
&|ty| Ty::new_imm_ptr(tcx, ty),
|
||||
),
|
||||
|
||||
(&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => {
|
||||
check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
|
||||
}
|
||||
(&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => check_mutbl(
|
||||
ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a },
|
||||
ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b },
|
||||
&|ty| Ty::new_imm_ptr(tcx, ty),
|
||||
),
|
||||
|
||||
(&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
|
||||
if def_a.is_struct() && def_b.is_struct() =>
|
||||
@ -551,7 +554,7 @@ fn infringing_fields_error(
|
||||
}
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
|
||||
trait_ref,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
polarity: ty::PredicatePolarity::Positive,
|
||||
..
|
||||
})) = error_predicate.kind().skip_binder()
|
||||
{
|
||||
|
@ -162,7 +162,7 @@ impl<'tcx> InherentCollect<'tcx> {
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(..)
|
||||
| ty::Never
|
||||
| ty::FnPtr(_)
|
||||
|
@ -323,7 +323,7 @@ fn emit_orphan_check_error<'tcx>(
|
||||
let is_foreign =
|
||||
!trait_ref.def_id.is_local() && matches!(is_target_ty, IsFirstInputType::No);
|
||||
|
||||
match &ty.kind() {
|
||||
match *ty.kind() {
|
||||
ty::Slice(_) => {
|
||||
push_to_foreign_or_name(
|
||||
is_foreign,
|
||||
@ -354,14 +354,14 @@ fn emit_orphan_check_error<'tcx>(
|
||||
ty::Alias(ty::Opaque, ..) => {
|
||||
opaque.push(errors::OnlyCurrentTraitsOpaque { span })
|
||||
}
|
||||
ty::RawPtr(ptr_ty) => {
|
||||
ty::RawPtr(ptr_ty, mutbl) => {
|
||||
if !self_ty.has_param() {
|
||||
let mut_key = ptr_ty.mutbl.prefix_str();
|
||||
let mut_key = mutbl.prefix_str();
|
||||
sugg = Some(errors::OnlyCurrentTraitsPointerSugg {
|
||||
wrapper_span: self_ty_span,
|
||||
struct_span: full_impl_span.shrink_to_lo(),
|
||||
mut_key,
|
||||
ptr_ty: ptr_ty.ty,
|
||||
ptr_ty,
|
||||
});
|
||||
}
|
||||
pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty });
|
||||
|
@ -624,7 +624,7 @@ pub(super) fn implied_predicates_with_filter(
|
||||
for &(pred, span) in implied_bounds {
|
||||
debug!("superbound: {:?}", pred);
|
||||
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());
|
||||
}
|
||||
@ -634,7 +634,7 @@ pub(super) fn implied_predicates_with_filter(
|
||||
for &(pred, span) in implied_bounds {
|
||||
debug!("superbound: {:?}", pred);
|
||||
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());
|
||||
}
|
||||
|
@ -140,16 +140,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
hir::GenericBound::Trait(poly_trait_ref, modifier) => {
|
||||
let (constness, polarity) = match modifier {
|
||||
hir::TraitBoundModifier::Const => {
|
||||
(ty::BoundConstness::Const, ty::ImplPolarity::Positive)
|
||||
(ty::BoundConstness::Const, ty::PredicatePolarity::Positive)
|
||||
}
|
||||
hir::TraitBoundModifier::MaybeConst => {
|
||||
(ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive)
|
||||
(ty::BoundConstness::ConstIfConst, ty::PredicatePolarity::Positive)
|
||||
}
|
||||
hir::TraitBoundModifier::None => {
|
||||
(ty::BoundConstness::NotConst, ty::ImplPolarity::Positive)
|
||||
(ty::BoundConstness::NotConst, ty::PredicatePolarity::Positive)
|
||||
}
|
||||
hir::TraitBoundModifier::Negative => {
|
||||
(ty::BoundConstness::NotConst, ty::ImplPolarity::Negative)
|
||||
(ty::BoundConstness::NotConst, ty::PredicatePolarity::Negative)
|
||||
}
|
||||
hir::TraitBoundModifier::Maybe => continue,
|
||||
};
|
||||
|
@ -673,7 +673,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
trait_ref: &hir::TraitRef<'tcx>,
|
||||
span: Span,
|
||||
constness: ty::BoundConstness,
|
||||
polarity: ty::ImplPolarity,
|
||||
polarity: ty::PredicatePolarity,
|
||||
self_ty: Ty<'tcx>,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
@ -710,7 +710,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
// Don't register additional associated type bounds for negative bounds,
|
||||
// since we should have emitten an error for them earlier, and they will
|
||||
// not be well-formed!
|
||||
if polarity == ty::ImplPolarity::Negative {
|
||||
if polarity != ty::PredicatePolarity::Positive {
|
||||
assert!(
|
||||
self.tcx().dcx().has_errors().is_some(),
|
||||
"negative trait bounds should not have bindings",
|
||||
@ -2299,14 +2299,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
self.lower_delegation_ty(*sig_id, *idx, hir_ty.span)
|
||||
}
|
||||
hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
|
||||
hir::TyKind::Ptr(mt) => {
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: self.lower_ty(mt.ty), mutbl: mt.mutbl })
|
||||
}
|
||||
hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
|
||||
hir::TyKind::Ref(region, mt) => {
|
||||
let r = self.lower_lifetime(region, None);
|
||||
debug!(?r);
|
||||
let t = self.lower_ty_common(mt.ty, true, false);
|
||||
Ty::new_ref(tcx, r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
|
||||
Ty::new_ref(tcx, r, t, mt.mutbl)
|
||||
}
|
||||
hir::TyKind::Never => tcx.types.never,
|
||||
hir::TyKind::Tup(fields) => {
|
||||
|
@ -43,7 +43,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
&trait_bound.trait_ref,
|
||||
trait_bound.span,
|
||||
ty::BoundConstness::NotConst,
|
||||
ty::ImplPolarity::Positive,
|
||||
ty::PredicatePolarity::Positive,
|
||||
dummy_self,
|
||||
&mut bounds,
|
||||
// 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();
|
||||
match bound_pred.skip_binder() {
|
||||
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));
|
||||
}
|
||||
ty::ClauseKind::Projection(proj) => {
|
||||
|
@ -435,6 +435,22 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
||||
&self,
|
||||
num_params_to_take: usize,
|
||||
) -> 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 is_used_in_input = |def_id| {
|
||||
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())
|
||||
.take(num_params_to_take)
|
||||
.map(|param| match param.kind {
|
||||
// This is being inferred from the item's inputs, no need to set it.
|
||||
ty::GenericParamDefKind::Type { .. } if is_used_in_input(param.def_id) => {
|
||||
"_".to_string()
|
||||
// If it's in method call (turbofish), it might be inferred from the expression (e.g. `.collect::<Vec<_>>()`)
|
||||
// If it is being inferred from the item's inputs, no need to set it.
|
||||
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<_>>()
|
||||
.join(", ")
|
||||
.intersperse(", ")
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_unbound_associated_types(&self) -> Vec<String> {
|
||||
|
@ -253,8 +253,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||
self.add_constraints_from_ty(current, typ, variance);
|
||||
}
|
||||
|
||||
ty::RawPtr(ref mt) => {
|
||||
self.add_constraints_from_mt(current, mt, variance);
|
||||
ty::RawPtr(ty, mutbl) => {
|
||||
self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
|
||||
}
|
||||
|
||||
ty::Tuple(subtys) => {
|
||||
|
@ -103,6 +103,8 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {
|
||||
*[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_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}`
|
||||
|
@ -128,7 +128,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
| ty::Float(_)
|
||||
| ty::Array(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
@ -332,13 +332,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
let mut sugg = None;
|
||||
let mut sugg_mutref = false;
|
||||
if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
|
||||
if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind()
|
||||
if let ty::RawPtr(expr_ty, _) = *self.expr_ty.kind()
|
||||
&& fcx.can_coerce(
|
||||
Ty::new_ref(
|
||||
fcx.tcx,
|
||||
fcx.tcx.lifetimes.re_erased,
|
||||
TypeAndMut { ty: expr_ty, mutbl },
|
||||
),
|
||||
Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, expr_ty, mutbl),
|
||||
self.cast_ty,
|
||||
)
|
||||
{
|
||||
@ -346,14 +342,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
} else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind()
|
||||
&& expr_mutbl == Mutability::Not
|
||||
&& mutbl == Mutability::Mut
|
||||
&& fcx.can_coerce(
|
||||
Ty::new_ref(
|
||||
fcx.tcx,
|
||||
expr_reg,
|
||||
TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut },
|
||||
),
|
||||
self.cast_ty,
|
||||
)
|
||||
&& fcx.can_coerce(Ty::new_mut_ref(fcx.tcx, expr_reg, expr_ty), self.cast_ty)
|
||||
{
|
||||
sugg_mutref = true;
|
||||
}
|
||||
@ -361,19 +350,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
if !sugg_mutref
|
||||
&& sugg == None
|
||||
&& fcx.can_coerce(
|
||||
Ty::new_ref(fcx.tcx, reg, TypeAndMut { ty: self.expr_ty, mutbl }),
|
||||
Ty::new_ref(fcx.tcx, reg, self.expr_ty, mutbl),
|
||||
self.cast_ty,
|
||||
)
|
||||
{
|
||||
sugg = Some((format!("&{}", mutbl.prefix_str()), false));
|
||||
}
|
||||
} else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind()
|
||||
} else if let ty::RawPtr(_, mutbl) = *self.cast_ty.kind()
|
||||
&& fcx.can_coerce(
|
||||
Ty::new_ref(
|
||||
fcx.tcx,
|
||||
fcx.tcx.lifetimes.re_erased,
|
||||
TypeAndMut { ty: self.expr_ty, mutbl },
|
||||
),
|
||||
Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, self.expr_ty, mutbl),
|
||||
self.cast_ty,
|
||||
)
|
||||
{
|
||||
@ -868,7 +853,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
// from a region pointer to a vector.
|
||||
|
||||
// Coerce to a raw pointer so that we generate AddressOf in MIR.
|
||||
let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr);
|
||||
let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl);
|
||||
fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
|
||||
.unwrap_or_else(|_| {
|
||||
bug!(
|
||||
|
@ -55,7 +55,7 @@ use rustc_middle::ty::adjustment::{
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::relate::RelateResult;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeAndMut};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::DesugaringKind;
|
||||
@ -222,8 +222,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
|
||||
// Examine the supertype and consider auto-borrowing.
|
||||
match *b.kind() {
|
||||
ty::RawPtr(mt_b) => {
|
||||
return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
|
||||
ty::RawPtr(_, b_mutbl) => {
|
||||
return self.coerce_unsafe_ptr(a, b, b_mutbl);
|
||||
}
|
||||
ty::Ref(r_b, _, mutbl_b) => {
|
||||
return self.coerce_borrowed_pointer(a, b, r_b, mutbl_b);
|
||||
@ -440,10 +440,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
let derefd_ty_a = Ty::new_ref(
|
||||
self.tcx,
|
||||
r,
|
||||
TypeAndMut {
|
||||
ty: referent_ty,
|
||||
mutbl: mutbl_b, // [1] above
|
||||
},
|
||||
referent_ty,
|
||||
mutbl_b, // [1] above
|
||||
);
|
||||
match self.unify(derefd_ty_a, b) {
|
||||
Ok(ok) => {
|
||||
@ -558,22 +556,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
Adjustment { kind: Adjust::Deref(None), target: ty_a },
|
||||
Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)),
|
||||
target: Ty::new_ref(
|
||||
self.tcx,
|
||||
r_borrow,
|
||||
ty::TypeAndMut { mutbl: mutbl_b, ty: ty_a },
|
||||
),
|
||||
target: Ty::new_ref(self.tcx, r_borrow, ty_a, mutbl_b),
|
||||
},
|
||||
))
|
||||
}
|
||||
(&ty::Ref(_, ty_a, mt_a), &ty::RawPtr(ty::TypeAndMut { mutbl: mt_b, .. })) => {
|
||||
(&ty::Ref(_, ty_a, mt_a), &ty::RawPtr(_, mt_b)) => {
|
||||
coerce_mutbls(mt_a, mt_b)?;
|
||||
|
||||
Some((
|
||||
Adjustment { kind: Adjust::Deref(None), target: ty_a },
|
||||
Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)),
|
||||
target: Ty::new_ptr(self.tcx, ty::TypeAndMut { mutbl: mt_b, ty: ty_a }),
|
||||
target: Ty::new_ptr(self.tcx, ty_a, mt_b),
|
||||
},
|
||||
))
|
||||
}
|
||||
@ -984,13 +978,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
|
||||
let (is_ref, mt_a) = match *a.kind() {
|
||||
ty::Ref(_, ty, mutbl) => (true, ty::TypeAndMut { ty, mutbl }),
|
||||
ty::RawPtr(mt) => (false, mt),
|
||||
ty::RawPtr(ty, mutbl) => (false, ty::TypeAndMut { ty, mutbl }),
|
||||
_ => return self.unify_and(a, b, identity),
|
||||
};
|
||||
coerce_mutbls(mt_a.mutbl, mutbl_b)?;
|
||||
|
||||
// Check that the types which they point at are compatible.
|
||||
let a_unsafe = Ty::new_ptr(self.tcx, ty::TypeAndMut { mutbl: mutbl_b, ty: mt_a.ty });
|
||||
let a_unsafe = Ty::new_ptr(self.tcx, mt_a.ty, mutbl_b);
|
||||
// Although references and unsafe ptrs have the same
|
||||
// representation, we still register an Adjust::DerefRef so that
|
||||
// regionck knows that the region for `a` must be valid here.
|
||||
|
@ -11,7 +11,7 @@ use rustc_middle::ty::Ty;
|
||||
use rustc_span::{
|
||||
edition::{Edition, LATEST_STABLE_EDITION},
|
||||
symbol::Ident,
|
||||
Span,
|
||||
Span, Symbol,
|
||||
};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -614,3 +614,10 @@ pub struct SuggestConvertViaMethod<'tcx> {
|
||||
pub expected: 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>,
|
||||
}
|
||||
|
@ -426,7 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
) -> Ty<'tcx> {
|
||||
let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
|
||||
match ty.kind() {
|
||||
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
|
||||
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
|
||||
if oprnd.is_syntactic_place_expr() {
|
||||
// Places may legitimately have unsized types.
|
||||
// For example, dereferences of a fat pointer and
|
||||
@ -442,12 +442,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let ty =
|
||||
self.check_expr_with_expectation_and_needs(oprnd, hint, Needs::maybe_mut_place(mutbl));
|
||||
|
||||
let tm = ty::TypeAndMut { ty, mutbl };
|
||||
match kind {
|
||||
_ if tm.ty.references_error() => Ty::new_misc_error(self.tcx),
|
||||
_ if ty.references_error() => Ty::new_misc_error(self.tcx),
|
||||
hir::BorrowKind::Raw => {
|
||||
self.check_named_place_expr(oprnd);
|
||||
Ty::new_ptr(self.tcx, tm)
|
||||
Ty::new_ptr(self.tcx, ty, mutbl)
|
||||
}
|
||||
hir::BorrowKind::Ref => {
|
||||
// Note: at this point, we cannot say what the best lifetime
|
||||
@ -465,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// whose address was taken can actually be made to live as long
|
||||
// as it needs to live.
|
||||
let region = self.next_region_var(infer::AddrOfRegion(expr.span));
|
||||
Ty::new_ref(self.tcx, region, tm)
|
||||
Ty::new_ref(self.tcx, region, ty, mutbl)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2686,8 +2685,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expr,
|
||||
Some(span),
|
||||
);
|
||||
} else if let ty::RawPtr(ty_and_mut) = expr_t.kind()
|
||||
&& let ty::Adt(adt_def, _) = ty_and_mut.ty.kind()
|
||||
} else if let ty::RawPtr(ptr_ty, _) = expr_t.kind()
|
||||
&& let ty::Adt(adt_def, _) = ptr_ty.kind()
|
||||
&& let ExprKind::Field(base_expr, _) = expr.kind
|
||||
&& adt_def.variants().len() == 1
|
||||
&& adt_def
|
||||
@ -3100,7 +3099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
cause.clone().derived_cause(
|
||||
ty::Binder::dummy(ty::TraitPredicate {
|
||||
trait_ref: impl_trait_ref,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
polarity: ty::PredicatePolarity::Positive,
|
||||
}),
|
||||
|derived| {
|
||||
traits::ImplDerivedObligation(Box::new(
|
||||
@ -3225,7 +3224,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.demand_coerce(expr, ty, fnptr_ty, None, AllowTwoPhase::No);
|
||||
}
|
||||
ty::Ref(_, base_ty, mutbl) => {
|
||||
let ptr_ty = Ty::new_ptr(self.tcx, ty::TypeAndMut { ty: base_ty, mutbl });
|
||||
let ptr_ty = Ty::new_ptr(self.tcx, base_ty, mutbl);
|
||||
self.demand_coerce(expr, ty, ptr_ty, None, AllowTwoPhase::No);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -1394,9 +1394,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
arg: &hir::Expr<'tcx>,
|
||||
err: &mut Diag<'tcx>,
|
||||
) {
|
||||
if let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Mut, .. }) = expected_ty.kind()
|
||||
&& let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Not, .. }) =
|
||||
provided_ty.kind()
|
||||
if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
|
||||
&& let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()
|
||||
&& let hir::ExprKind::Call(callee, _) = arg.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
|
||||
&& let Res::Def(_, def_id) = path.res
|
||||
|
@ -7,7 +7,6 @@ use crate::hir::is_range_literal;
|
||||
use crate::method::probe;
|
||||
use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
|
||||
use crate::rustc_middle::ty::Article;
|
||||
use crate::ty::TypeAndMut;
|
||||
use core::cmp::min;
|
||||
use core::iter;
|
||||
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
|
||||
@ -889,7 +888,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.dcx(),
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -899,6 +899,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
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
|
||||
/// 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`
|
||||
@ -1479,7 +1496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expected_ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
// Expected type needs to be a raw pointer.
|
||||
let ty::RawPtr(ty::TypeAndMut { mutbl, .. }) = expected_ty.kind() else {
|
||||
let ty::RawPtr(_, mutbl) = expected_ty.kind() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
@ -2509,11 +2526,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return make_sugg(sp, expr.span.lo());
|
||||
}
|
||||
}
|
||||
(
|
||||
_,
|
||||
&ty::RawPtr(TypeAndMut { ty: ty_b, mutbl: mutbl_b }),
|
||||
&ty::Ref(_, ty_a, mutbl_a),
|
||||
) => {
|
||||
(_, &ty::RawPtr(ty_b, mutbl_b), &ty::Ref(_, ty_a, mutbl_a)) => {
|
||||
if let Some(steps) = self.deref_steps(ty_a, ty_b)
|
||||
// Only suggest valid if dereferencing needed.
|
||||
&& steps > 0
|
||||
|
@ -268,11 +268,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
adjustment::Adjust::Deref(overloaded) => {
|
||||
// Equivalent to *expr or something similar.
|
||||
let base = if let Some(deref) = overloaded {
|
||||
let ref_ty = Ty::new_ref(
|
||||
self.tcx(),
|
||||
deref.region,
|
||||
ty::TypeAndMut { ty: target, mutbl: deref.mutbl },
|
||||
);
|
||||
let ref_ty = Ty::new_ref(self.tcx(), deref.region, target, deref.mutbl);
|
||||
self.cat_rvalue(expr.hir_id, ref_ty)
|
||||
} else {
|
||||
previous()?
|
||||
@ -479,7 +475,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
let ty::Ref(region, _, mutbl) = *base_ty.kind() else {
|
||||
span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
|
||||
};
|
||||
let ref_ty = Ty::new_ref(self.tcx(), region, ty::TypeAndMut { ty: place_ty, mutbl });
|
||||
let ref_ty = Ty::new_ref(self.tcx(), region, place_ty, mutbl);
|
||||
|
||||
let base = self.cat_rvalue(expr.hir_id, ref_ty);
|
||||
self.cat_deref(expr, base)
|
||||
|
@ -188,7 +188,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
// Type we're wrapping in a reference, used later for unsizing
|
||||
let base_ty = target;
|
||||
|
||||
target = Ty::new_ref(self.tcx, region, ty::TypeAndMut { mutbl, ty: target });
|
||||
target = Ty::new_ref(self.tcx, region, target, mutbl);
|
||||
|
||||
// Method call receivers are the primary use case
|
||||
// for two-phase borrows.
|
||||
@ -208,11 +208,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
base_ty
|
||||
)
|
||||
};
|
||||
target = Ty::new_ref(
|
||||
self.tcx,
|
||||
region,
|
||||
ty::TypeAndMut { mutbl: mutbl.into(), ty: unsized_ty },
|
||||
);
|
||||
target = Ty::new_ref(self.tcx, region, unsized_ty, mutbl.into());
|
||||
adjustments.push(Adjustment {
|
||||
kind: Adjust::Pointer(PointerCoercion::Unsize),
|
||||
target,
|
||||
@ -221,9 +217,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
}
|
||||
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) => {
|
||||
target = match target.kind() {
|
||||
&ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
|
||||
&ty::RawPtr(ty, mutbl) => {
|
||||
assert!(mutbl.is_mut());
|
||||
Ty::new_ptr(self.tcx, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty })
|
||||
Ty::new_imm_ptr(self.tcx, ty)
|
||||
}
|
||||
other => panic!("Cannot adjust receiver type {other:?} to const ptr"),
|
||||
};
|
||||
|
@ -200,11 +200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if let Some(span) = result.illegal_sized_bound {
|
||||
let mut needs_mut = false;
|
||||
if let ty::Ref(region, t_type, mutability) = self_ty.kind() {
|
||||
let trait_type = Ty::new_ref(
|
||||
self.tcx,
|
||||
*region,
|
||||
ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
|
||||
);
|
||||
let trait_type = Ty::new_ref(self.tcx, *region, *t_type, mutability.invert());
|
||||
// We probe again to see if there might be a borrow mutability discrepancy.
|
||||
match self.lookup_probe(
|
||||
segment.ident,
|
||||
|
@ -528,7 +528,7 @@ fn method_autoderef_steps<'tcx>(
|
||||
from_unsafe_deref: reached_raw_pointer,
|
||||
unsize: false,
|
||||
};
|
||||
if let ty::RawPtr(_) = ty.kind() {
|
||||
if let ty::RawPtr(_, _) = ty.kind() {
|
||||
// all the subsequent steps will be from_unsafe_deref
|
||||
reached_raw_pointer = true;
|
||||
}
|
||||
@ -696,7 +696,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(..)
|
||||
| ty::Never
|
||||
| ty::Tuple(..) => self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty),
|
||||
@ -1213,7 +1213,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
// In general, during probing we erase regions.
|
||||
let region = tcx.lifetimes.re_erased;
|
||||
|
||||
let autoref_ty = Ty::new_ref(tcx, region, ty::TypeAndMut { ty: self_ty, mutbl });
|
||||
let autoref_ty = Ty::new_ref(tcx, region, self_ty, mutbl);
|
||||
self.pick_method(autoref_ty, unstable_candidates).map(|r| {
|
||||
r.map(|mut pick| {
|
||||
pick.autoderefs = step.autoderefs;
|
||||
@ -1238,12 +1238,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let &ty::RawPtr(ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut }) = self_ty.kind() else {
|
||||
let &ty::RawPtr(ty, hir::Mutability::Mut) = self_ty.kind() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let const_self_ty = ty::TypeAndMut { ty, mutbl: hir::Mutability::Not };
|
||||
let const_ptr_ty = Ty::new_ptr(self.tcx, const_self_ty);
|
||||
let const_ptr_ty = Ty::new_imm_ptr(self.tcx, ty);
|
||||
self.pick_method(const_ptr_ty, unstable_candidates).map(|r| {
|
||||
r.map(|mut pick| {
|
||||
pick.autoderefs = step.autoderefs;
|
||||
|
@ -304,11 +304,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
|
||||
if needs_mut {
|
||||
let trait_type = Ty::new_ref(
|
||||
self.tcx,
|
||||
*region,
|
||||
ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
|
||||
);
|
||||
let trait_type =
|
||||
Ty::new_ref(self.tcx, *region, *t_type, mutability.invert());
|
||||
let msg = format!("you need `{trait_type}` instead of `{rcvr_ty}`");
|
||||
let mut kind = &self_expr.kind;
|
||||
while let hir::ExprKind::AddrOf(_, _, expr)
|
||||
@ -533,7 +530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
if let ty::RawPtr(_) = &rcvr_ty.kind() {
|
||||
if let ty::RawPtr(_, _) = &rcvr_ty.kind() {
|
||||
err.note(
|
||||
"try using `<*const T>::as_ref()` to get a reference to the \
|
||||
type behind the pointer: https://doc.rust-lang.org/std/\
|
||||
@ -875,7 +872,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||
Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
|
||||
&& pred.polarity == ty::ImplPolarity::Positive
|
||||
&& pred.polarity == ty::PredicatePolarity::Positive
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
@ -3367,7 +3364,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
"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| {
|
||||
let imp = header.trait_ref.instantiate_identity();
|
||||
let imp_simp =
|
||||
|
@ -508,11 +508,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
suggest_deref_binop(&mut err, *lhs_deref_ty);
|
||||
} else {
|
||||
let lhs_inv_mutbl = mutbl.invert();
|
||||
let lhs_inv_mutbl_ty = Ty::new_ref(
|
||||
self.tcx,
|
||||
*region,
|
||||
ty::TypeAndMut { ty: *lhs_deref_ty, mutbl: lhs_inv_mutbl },
|
||||
);
|
||||
let lhs_inv_mutbl_ty =
|
||||
Ty::new_ref(self.tcx, *region, *lhs_deref_ty, lhs_inv_mutbl);
|
||||
|
||||
suggest_different_borrow(
|
||||
&mut err,
|
||||
@ -524,11 +521,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
if let Ref(region, rhs_deref_ty, mutbl) = rhs_ty.kind() {
|
||||
let rhs_inv_mutbl = mutbl.invert();
|
||||
let rhs_inv_mutbl_ty = Ty::new_ref(
|
||||
self.tcx,
|
||||
*region,
|
||||
ty::TypeAndMut { ty: *rhs_deref_ty, mutbl: rhs_inv_mutbl },
|
||||
);
|
||||
let rhs_inv_mutbl_ty =
|
||||
Ty::new_ref(self.tcx, *region, *rhs_deref_ty, rhs_inv_mutbl);
|
||||
|
||||
suggest_different_borrow(
|
||||
&mut err,
|
||||
|
@ -2057,8 +2057,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// Create a reference type with a fresh region variable.
|
||||
fn new_ref_ty(&self, span: Span, mutbl: hir::Mutability, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let region = self.next_region_var(infer::PatternRegion(span));
|
||||
let mt = ty::TypeAndMut { ty, mutbl };
|
||||
Ty::new_ref(self.tcx, region, mt)
|
||||
Ty::new_ref(self.tcx, region, ty, mutbl)
|
||||
}
|
||||
|
||||
fn try_resolve_slice_ty_to_array_ty(
|
||||
|
@ -162,11 +162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if let ty::Ref(region, _, hir::Mutability::Not) = method.sig.inputs()[0].kind() {
|
||||
adjustments.push(Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(*region, AutoBorrowMutability::Not)),
|
||||
target: Ty::new_ref(
|
||||
self.tcx,
|
||||
*region,
|
||||
ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: adjusted_ty },
|
||||
),
|
||||
target: Ty::new_imm_ref(self.tcx, *region, adjusted_ty),
|
||||
});
|
||||
} else {
|
||||
span_bug!(expr.span, "input to index is not a ref?");
|
||||
@ -400,11 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
allow_two_phase_borrow: AllowTwoPhase::No,
|
||||
};
|
||||
adjustment.kind = Adjust::Borrow(AutoBorrow::Ref(*region, mutbl));
|
||||
adjustment.target = Ty::new_ref(
|
||||
self.tcx,
|
||||
*region,
|
||||
ty::TypeAndMut { ty: source, mutbl: mutbl.into() },
|
||||
);
|
||||
adjustment.target = Ty::new_ref(self.tcx, *region, source, mutbl.into());
|
||||
}
|
||||
source = adjustment.target;
|
||||
}
|
||||
|
@ -1719,7 +1719,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
for pointer_ty in place.deref_tys() {
|
||||
match pointer_ty.kind() {
|
||||
// We don't capture derefs of raw ptrs
|
||||
ty::RawPtr(_) => unreachable!(),
|
||||
ty::RawPtr(_, _) => unreachable!(),
|
||||
|
||||
// Dereferencing a mut-ref allows us to mut the Place if we don't deref
|
||||
// an immut-ref after on top of this.
|
||||
@ -1780,11 +1780,9 @@ fn apply_capture_kind_on_capture_ty<'tcx>(
|
||||
) -> Ty<'tcx> {
|
||||
match capture_kind {
|
||||
ty::UpvarCapture::ByValue => ty,
|
||||
ty::UpvarCapture::ByRef(kind) => Ty::new_ref(
|
||||
tcx,
|
||||
region.unwrap(),
|
||||
ty::TypeAndMut { ty: ty, mutbl: kind.to_mutbl_lossy() },
|
||||
),
|
||||
ty::UpvarCapture::ByRef(kind) => {
|
||||
Ty::new_ref(tcx, region.unwrap(), ty, kind.to_mutbl_lossy())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,7 @@ impl<T> Trait<T> for X {
|
||||
.any(|(pred, _span)| match pred.kind().skip_binder() {
|
||||
ty::ClauseKind::Trait(trait_predicate)
|
||||
if trait_predicate.polarity
|
||||
== ty::ImplPolarity::Positive =>
|
||||
== ty::PredicatePolarity::Positive =>
|
||||
{
|
||||
trait_predicate.def_id() == def_id
|
||||
}
|
||||
@ -420,7 +420,7 @@ impl<T> Trait<T> for X {
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
if trait_predicate.polarity != ty::ImplPolarity::Positive {
|
||||
if trait_predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
continue;
|
||||
}
|
||||
let def_id = trait_predicate.def_id();
|
||||
|
@ -209,7 +209,7 @@ impl<'tcx> FulfillmentError<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> PolyTraitObligation<'tcx> {
|
||||
pub fn polarity(&self) -> ty::ImplPolarity {
|
||||
pub fn polarity(&self) -> ty::PredicatePolarity {
|
||||
self.predicate.skip_binder().polarity
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
||||
match bound_clause.skip_binder() {
|
||||
ty::ClauseKind::Trait(data) => {
|
||||
// Negative trait bounds do not imply any supertrait bounds
|
||||
if data.polarity == ty::ImplPolarity::Negative {
|
||||
if data.polarity != ty::PredicatePolarity::Positive {
|
||||
return;
|
||||
}
|
||||
// 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>,
|
||||
) -> bool {
|
||||
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 {
|
||||
cause: traits::ObligationCause::dummy(),
|
||||
param_env,
|
||||
@ -2477,7 +2477,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
||||
Adt(..) if ty.is_box() => Some("`Box` must be non-null".into()),
|
||||
FnPtr(..) => Some("function pointers must be non-null".into()),
|
||||
Never => Some("the `!` type has no valid value".into()),
|
||||
RawPtr(tm) if matches!(tm.ty.kind(), Dynamic(..)) =>
|
||||
RawPtr(ty, _) if matches!(ty.kind(), Dynamic(..)) =>
|
||||
// raw ptr to dyn Trait
|
||||
{
|
||||
Some("the vtable of a wide raw pointer must be non-null".into())
|
||||
@ -2493,7 +2493,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
||||
Some("integers must be initialized".into())
|
||||
}
|
||||
Float(_) if init == InitKind::Uninit => Some("floats must be initialized".into()),
|
||||
RawPtr(_) if init == InitKind::Uninit => {
|
||||
RawPtr(_, _) if init == InitKind::Uninit => {
|
||||
Some("raw pointers must be initialized".into())
|
||||
}
|
||||
// Recurse and checks for some compound types. (but not unions)
|
||||
|
@ -322,10 +322,10 @@ fn structurally_same_type_impl<'tcx>(
|
||||
(Slice(a_ty), Slice(b_ty)) => {
|
||||
structurally_same_type_impl(seen_types, tcx, param_env, *a_ty, *b_ty, ckind)
|
||||
}
|
||||
(RawPtr(a_tymut), RawPtr(b_tymut)) => {
|
||||
a_tymut.mutbl == b_tymut.mutbl
|
||||
(RawPtr(a_ty, a_mutbl), RawPtr(b_ty, b_mutbl)) => {
|
||||
a_mutbl == b_mutbl
|
||||
&& structurally_same_type_impl(
|
||||
seen_types, tcx, param_env, a_tymut.ty, b_tymut.ty, ckind,
|
||||
seen_types, tcx, param_env, *a_ty, *b_ty, ckind,
|
||||
)
|
||||
}
|
||||
(Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_hir::{Expr, ExprKind, UnOp};
|
||||
use rustc_middle::ty::layout::LayoutOf as _;
|
||||
use rustc_middle::ty::{self, layout::TyAndLayout, TypeAndMut};
|
||||
use rustc_middle::ty::{self, layout::TyAndLayout};
|
||||
use rustc_span::sym;
|
||||
|
||||
use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext};
|
||||
@ -153,7 +153,7 @@ fn is_cast_from_ref_to_mut_ptr<'tcx>(
|
||||
let end_ty = cx.typeck_results().node_type(orig_expr.hir_id);
|
||||
|
||||
// Bail out early if the end type is **not** a mutable pointer.
|
||||
if !matches!(end_ty.kind(), ty::RawPtr(TypeAndMut { ty: _, mutbl: Mutability::Mut })) {
|
||||
if !matches!(end_ty.kind(), ty::RawPtr(_, Mutability::Mut)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ fn is_cast_to_bigger_memory_layout<'tcx>(
|
||||
) -> Option<(TyAndLayout<'tcx>, TyAndLayout<'tcx>, Expr<'tcx>)> {
|
||||
let end_ty = cx.typeck_results().node_type(orig_expr.hir_id);
|
||||
|
||||
let ty::RawPtr(TypeAndMut { ty: inner_end_ty, mutbl: _ }) = end_ty.kind() else {
|
||||
let ty::RawPtr(inner_end_ty, _) = end_ty.kind() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
@ -18,10 +18,10 @@ use rustc_errors::DiagMessage;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
|
||||
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_middle::ty::{GenericArgsRef, TypeAndMut};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::source_map;
|
||||
use rustc_span::symbol::sym;
|
||||
@ -673,7 +673,7 @@ fn lint_wide_pointer<'tcx>(
|
||||
refs += 1;
|
||||
}
|
||||
match ty.kind() {
|
||||
ty::RawPtr(TypeAndMut { mutbl: _, ty }) => (!ty.is_sized(cx.tcx, cx.param_env))
|
||||
ty::RawPtr(ty, _) => (!ty.is_sized(cx.tcx, cx.param_env))
|
||||
.then(|| (refs, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))),
|
||||
_ => None,
|
||||
}
|
||||
@ -1046,10 +1046,10 @@ fn get_nullable_type<'tcx>(
|
||||
}
|
||||
ty::Int(ty) => Ty::new_int(tcx, ty),
|
||||
ty::Uint(ty) => Ty::new_uint(tcx, ty),
|
||||
ty::RawPtr(ty_mut) => Ty::new_ptr(tcx, ty_mut),
|
||||
ty::RawPtr(ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
|
||||
// As these types are always non-null, the nullable equivalent of
|
||||
// `Option<T>` of these types are their raw pointer counterparts.
|
||||
ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty::TypeAndMut { ty, mutbl }),
|
||||
ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
|
||||
// There is no nullable equivalent for Rust's function pointers,
|
||||
// you must use an `Option<fn(..) -> _>` to represent it.
|
||||
ty::FnPtr(..) => ty,
|
||||
@ -1374,7 +1374,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
help: Some(fluent::lint_improper_ctypes_tuple_help),
|
||||
},
|
||||
|
||||
ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _)
|
||||
ty::RawPtr(ty, _) | ty::Ref(_, ty, _)
|
||||
if {
|
||||
matches!(self.mode, CItemKind::Definition)
|
||||
&& ty.is_sized(self.cx.tcx, self.cx.param_env)
|
||||
@ -1383,7 +1383,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
FfiSafe
|
||||
}
|
||||
|
||||
ty::RawPtr(ty::TypeAndMut { ty, .. })
|
||||
ty::RawPtr(ty, _)
|
||||
if match ty.kind() {
|
||||
ty::Tuple(tuple) => tuple.is_empty(),
|
||||
_ => false,
|
||||
@ -1392,9 +1392,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
FfiSafe
|
||||
}
|
||||
|
||||
ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => {
|
||||
self.check_type_for_ffi(cache, ty)
|
||||
}
|
||||
ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => self.check_type_for_ffi(cache, ty),
|
||||
|
||||
ty::Array(inner_ty, _) => self.check_type_for_ffi(cache, inner_ty),
|
||||
|
||||
|
@ -170,11 +170,11 @@ impl<'tcx> Rvalue<'tcx> {
|
||||
Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did),
|
||||
Rvalue::Ref(reg, bk, ref place) => {
|
||||
let place_ty = place.ty(local_decls, tcx).ty;
|
||||
Ty::new_ref(tcx, reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() })
|
||||
Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy())
|
||||
}
|
||||
Rvalue::AddressOf(mutability, ref place) => {
|
||||
let place_ty = place.ty(local_decls, tcx).ty;
|
||||
Ty::new_ptr(tcx, ty::TypeAndMut { ty: place_ty, mutbl: mutability })
|
||||
Ty::new_ptr(tcx, place_ty, mutability)
|
||||
}
|
||||
Rvalue::Len(..) => tcx.types.usize,
|
||||
Rvalue::Cast(.., ty) => ty,
|
||||
|
@ -234,6 +234,7 @@ trivial! {
|
||||
Option<rustc_middle::middle::stability::DeprecationEntry>,
|
||||
Option<rustc_middle::ty::Destructor>,
|
||||
Option<rustc_middle::ty::ImplTraitInTraitData>,
|
||||
Option<rustc_middle::ty::ScalarInt>,
|
||||
Option<rustc_span::def_id::CrateNum>,
|
||||
Option<rustc_span::def_id::DefId>,
|
||||
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_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi;
|
||||
|
||||
/// Placeholder for `CrateNum`'s "local" counterpart
|
||||
#[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) {
|
||||
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.
|
||||
///
|
||||
/// **Do not use this** directly, use the `eval_to_const_value` or `eval_to_valtree` instead.
|
||||
|
@ -69,7 +69,7 @@ impl<'tcx> CastTy<'tcx> {
|
||||
ty::Uint(u) => Some(CastTy::Int(IntTy::U(u))),
|
||||
ty::Float(_) => Some(CastTy::Float),
|
||||
ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)),
|
||||
ty::RawPtr(mt) => Some(CastTy::Ptr(mt)),
|
||||
ty::RawPtr(ty, mutbl) => Some(CastTy::Ptr(ty::TypeAndMut { ty, mutbl })),
|
||||
ty::FnPtr(..) => Some(CastTy::FnPtr),
|
||||
ty::Dynamic(_, _, ty::DynStar) => Some(CastTy::DynStar),
|
||||
_ => None,
|
||||
|
@ -27,8 +27,8 @@ use crate::traits::solve::{
|
||||
use crate::ty::{
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind,
|
||||
ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate,
|
||||
PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
|
||||
TypeVisitable, Visibility,
|
||||
PredicateKind, PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty,
|
||||
TyKind, TyVid, TypeVisitable, Visibility,
|
||||
};
|
||||
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
||||
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>}
|
||||
|
||||
TrivialLiftImpls! {
|
||||
ImplPolarity, Promoted
|
||||
ImplPolarity, PredicatePolarity, Promoted
|
||||
}
|
||||
|
||||
macro_rules! sty_debug_print {
|
||||
@ -1833,7 +1833,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
return false;
|
||||
};
|
||||
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> {
|
||||
Mismatch,
|
||||
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
|
||||
PolarityMismatch(ExpectedFound<ty::ImplPolarity>),
|
||||
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
|
||||
UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
|
||||
AbiMismatch(ExpectedFound<abi::Abi>),
|
||||
Mutability,
|
||||
@ -286,7 +286,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
ty::Foreign(_) => "extern type".into(),
|
||||
ty::Array(..) => "array".into(),
|
||||
ty::Slice(_) => "slice".into(),
|
||||
ty::RawPtr(_) => "raw pointer".into(),
|
||||
ty::RawPtr(_, _) => "raw pointer".into(),
|
||||
ty::Ref(.., mutbl) => match mutbl {
|
||||
hir::Mutability::Mut => "mutable reference",
|
||||
_ => "reference",
|
||||
|
@ -120,7 +120,7 @@ pub fn simplify_type<'tcx>(
|
||||
ty::Str => Some(SimplifiedType::Str),
|
||||
ty::Array(..) => Some(SimplifiedType::Array),
|
||||
ty::Slice(..) => Some(SimplifiedType::Slice),
|
||||
ty::RawPtr(ptr) => Some(SimplifiedType::Ptr(ptr.mutbl)),
|
||||
ty::RawPtr(_, mutbl) => Some(SimplifiedType::Ptr(mutbl)),
|
||||
ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() {
|
||||
Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
|
||||
Some(SimplifiedType::Trait(principal_def_id))
|
||||
@ -286,8 +286,10 @@ impl DeepRejectCtxt {
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
ty::RawPtr(obl) => match k {
|
||||
ty::RawPtr(imp) => obl.mutbl == imp.mutbl && self.types_may_unify(obl.ty, imp.ty),
|
||||
ty::RawPtr(obl_ty, obl_mutbl) => match *k {
|
||||
ty::RawPtr(imp_ty, imp_mutbl) => {
|
||||
obl_mutbl == imp_mutbl && self.types_may_unify(obl_ty, imp_ty)
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
ty::Dynamic(obl_preds, ..) => {
|
||||
|
@ -211,8 +211,8 @@ impl FlagComputation {
|
||||
|
||||
&ty::Slice(tt) => self.add_ty(tt),
|
||||
|
||||
ty::RawPtr(m) => {
|
||||
self.add_ty(m.ty);
|
||||
&ty::RawPtr(ty, _) => {
|
||||
self.add_ty(ty);
|
||||
}
|
||||
|
||||
&ty::Ref(r, ty, _) => {
|
||||
|
@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::bit_set::FiniteBitSet;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
@ -172,6 +173,11 @@ impl<'tcx> Instance<'tcx> {
|
||||
// If this a non-generic instance, it cannot be a shared monomorphization.
|
||||
self.args.non_erasable_generics(tcx, self.def_id()).next()?;
|
||||
|
||||
// compiler_builtins cannot use upstream monomorphizations.
|
||||
if tcx.is_compiler_builtins(LOCAL_CRATE) {
|
||||
return None;
|
||||
}
|
||||
|
||||
match self.def {
|
||||
InstanceDef::Item(def) => tcx
|
||||
.upstream_monomorphizations_for(def)
|
||||
|
@ -328,7 +328,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
||||
};
|
||||
|
||||
match *ty.kind() {
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
|
||||
let non_zero = !ty.is_unsafe_ptr();
|
||||
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
|
||||
match tail.kind() {
|
||||
@ -345,11 +345,16 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
||||
ty::Array(inner, len)
|
||||
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)? {
|
||||
// This may succeed because the multiplication of two types may overflow
|
||||
// but a single size of a nested array will not.
|
||||
SizeSkeleton::Known(s) => {
|
||||
if let Some(c) = len.try_eval_target_usize(tcx, param_env) {
|
||||
if let Some(c) = len_eval {
|
||||
let size = s
|
||||
.bytes()
|
||||
.checked_mul(c)
|
||||
@ -742,7 +747,7 @@ where
|
||||
}
|
||||
|
||||
// Potentially-fat pointers.
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
|
||||
assert!(i < this.fields.count());
|
||||
|
||||
// Reuse the fat `*T` type as its own thin pointer data field.
|
||||
@ -920,8 +925,8 @@ where
|
||||
let param_env = cx.param_env();
|
||||
|
||||
let pointee_info = match *this.ty.kind() {
|
||||
ty::RawPtr(mt) if offset.bytes() == 0 => {
|
||||
tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo {
|
||||
ty::RawPtr(p_ty, _) if offset.bytes() == 0 => {
|
||||
tcx.layout_of(param_env.and(p_ty)).ok().map(|layout| PointeeInfo {
|
||||
size: layout.size,
|
||||
align: layout.align.abi,
|
||||
safe: None,
|
||||
|
@ -280,17 +280,6 @@ pub enum ImplPolarity {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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(TypeFoldable, TypeVisitable)]
|
||||
pub enum Asyncness {
|
||||
|
@ -11,7 +11,7 @@ use std::cmp::Ordering;
|
||||
use crate::ty::visit::TypeVisitableExt;
|
||||
use crate::ty::{
|
||||
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>>;
|
||||
@ -70,7 +70,7 @@ impl<'tcx> Predicate<'tcx> {
|
||||
polarity,
|
||||
})) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
|
||||
trait_ref,
|
||||
polarity: polarity.flip()?,
|
||||
polarity: polarity.flip(),
|
||||
}))),
|
||||
|
||||
_ => None,
|
||||
@ -663,7 +663,7 @@ pub struct TraitPredicate<'tcx> {
|
||||
/// exist via a series of predicates.)
|
||||
///
|
||||
/// If polarity is Reserved: that's a bug.
|
||||
pub polarity: ImplPolarity,
|
||||
pub polarity: PredicatePolarity,
|
||||
}
|
||||
|
||||
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
|
||||
@ -693,7 +693,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn polarity(self) -> ImplPolarity {
|
||||
pub fn polarity(self) -> PredicatePolarity {
|
||||
self.skip_binder().polarity
|
||||
}
|
||||
}
|
||||
@ -907,7 +907,7 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
|
||||
impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
|
||||
#[inline(always)]
|
||||
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> {
|
||||
self.map_bound(|trait_ref| TraitPredicate {
|
||||
trait_ref,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
polarity: ty::PredicatePolarity::Positive,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ fn characteristic_def_id_of_type_cached<'a>(
|
||||
characteristic_def_id_of_type_cached(subty, visited)
|
||||
}
|
||||
|
||||
ty::RawPtr(mt) => characteristic_def_id_of_type_cached(mt.ty, visited),
|
||||
ty::RawPtr(ty, _) => characteristic_def_id_of_type_cached(ty, visited),
|
||||
|
||||
ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited),
|
||||
|
||||
|
@ -667,15 +667,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
ty::Int(t) => p!(write("{}", t.name_str())),
|
||||
ty::Uint(t) => p!(write("{}", t.name_str())),
|
||||
ty::Float(t) => p!(write("{}", t.name_str())),
|
||||
ty::RawPtr(ref tm) => {
|
||||
ty::RawPtr(ty, mutbl) => {
|
||||
p!(write(
|
||||
"*{} ",
|
||||
match tm.mutbl {
|
||||
match mutbl {
|
||||
hir::Mutability::Mut => "mut",
|
||||
hir::Mutability::Not => "const",
|
||||
}
|
||||
));
|
||||
p!(print(tm.ty))
|
||||
p!(print(ty))
|
||||
}
|
||||
ty::Ref(r, ty, mutbl) => {
|
||||
p!("&");
|
||||
@ -995,11 +995,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
// Don't print `+ Sized`, but rather `+ ?Sized` if absent.
|
||||
if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
|
||||
match pred.polarity {
|
||||
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => {
|
||||
ty::PredicatePolarity::Positive => {
|
||||
has_sized_bound = true;
|
||||
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(
|
||||
trait_ref,
|
||||
ty::ImplPolarity::Positive,
|
||||
ty::PredicatePolarity::Positive,
|
||||
Some(proj_ty),
|
||||
&mut traits,
|
||||
&mut fn_traits,
|
||||
@ -1085,7 +1085,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
_ => {
|
||||
if entry.has_fn_once {
|
||||
traits
|
||||
.entry((fn_once_trait_ref, ty::ImplPolarity::Positive))
|
||||
.entry((fn_once_trait_ref, ty::PredicatePolarity::Positive))
|
||||
.or_default()
|
||||
.extend(
|
||||
// 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 {
|
||||
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 {
|
||||
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| {
|
||||
define_scoped_cx!(cx);
|
||||
|
||||
if polarity == ty::ImplPolarity::Negative {
|
||||
if polarity == ty::PredicatePolarity::Negative {
|
||||
p!("!");
|
||||
}
|
||||
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(
|
||||
&mut self,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
polarity: ty::ImplPolarity,
|
||||
polarity: ty::PredicatePolarity,
|
||||
proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>,
|
||||
traits: &mut FxIndexMap<
|
||||
(ty::PolyTraitRef<'tcx>, ty::ImplPolarity),
|
||||
(ty::PolyTraitRef<'tcx>, ty::PredicatePolarity),
|
||||
FxIndexMap<DefId, ty::Binder<'tcx, Term<'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
|
||||
// super-trait ref and record it there.
|
||||
// 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()
|
||||
{
|
||||
// If we have a FnOnce, then insert it into
|
||||
@ -1752,7 +1752,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
p!(write("{:?}", char::try_from(int).unwrap()))
|
||||
}
|
||||
// Pointer types
|
||||
ty::Ref(..) | ty::RawPtr(_) | ty::FnPtr(_) => {
|
||||
ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(_) => {
|
||||
let data = int.assert_bits(self.tcx().data_layout.pointer_size);
|
||||
self.typed_value(
|
||||
|this| {
|
||||
@ -3139,7 +3139,7 @@ define_print_and_forward_display! {
|
||||
|
||||
TraitPredPrintModifiersAndPath<'tcx> {
|
||||
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!(print(self.0.trait_ref.print_only_trait_path()));
|
||||
@ -3172,7 +3172,7 @@ define_print_and_forward_display! {
|
||||
ty::TraitPredicate<'tcx> {
|
||||
p!(print(self.trait_ref.self_ty()), ": ");
|
||||
p!(pretty_print_bound_constness(self.trait_ref));
|
||||
if let ty::ImplPolarity::Negative = self.polarity {
|
||||
if let ty::PredicatePolarity::Negative = self.polarity {
|
||||
p!("!");
|
||||
}
|
||||
p!(print(self.trait_ref.print_trait_sugared()))
|
||||
|
@ -94,28 +94,6 @@ pub trait Relate<'tcx>: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Relate impls
|
||||
|
||||
pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::TypeAndMut<'tcx>,
|
||||
b: ty::TypeAndMut<'tcx>,
|
||||
base_ty: Ty<'tcx>,
|
||||
) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> {
|
||||
debug!("{}.mts({:?}, {:?})", relation.tag(), a, b);
|
||||
if a.mutbl != b.mutbl {
|
||||
Err(TypeError::Mutability)
|
||||
} else {
|
||||
let mutbl = a.mutbl;
|
||||
let (variance, info) = match mutbl {
|
||||
hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
|
||||
hir::Mutability::Mut => {
|
||||
(ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: base_ty, param_index: 0 })
|
||||
}
|
||||
};
|
||||
let ty = relation.relate_with_variance(variance, info, a.ty, b.ty)?;
|
||||
Ok(ty::TypeAndMut { ty, mutbl })
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn relate_args_invariantly<'tcx, R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
@ -465,17 +443,39 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||
Ok(Ty::new_coroutine_closure(tcx, a_id, args))
|
||||
}
|
||||
|
||||
(&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
|
||||
let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?;
|
||||
Ok(Ty::new_ptr(tcx, mt))
|
||||
(&ty::RawPtr(a_ty, a_mutbl), &ty::RawPtr(b_ty, b_mutbl)) => {
|
||||
if a_mutbl != b_mutbl {
|
||||
return Err(TypeError::Mutability);
|
||||
}
|
||||
|
||||
let (variance, info) = match a_mutbl {
|
||||
hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
|
||||
hir::Mutability::Mut => {
|
||||
(ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
|
||||
}
|
||||
};
|
||||
|
||||
let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
|
||||
|
||||
Ok(Ty::new_ptr(tcx, ty, a_mutbl))
|
||||
}
|
||||
|
||||
(&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
|
||||
if a_mutbl != b_mutbl {
|
||||
return Err(TypeError::Mutability);
|
||||
}
|
||||
|
||||
let (variance, info) = match a_mutbl {
|
||||
hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
|
||||
hir::Mutability::Mut => {
|
||||
(ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
|
||||
}
|
||||
};
|
||||
|
||||
let r = relation.relate(a_r, b_r)?;
|
||||
let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
|
||||
let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
|
||||
let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?;
|
||||
Ok(Ty::new_ref(tcx, r, mt))
|
||||
let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
|
||||
|
||||
Ok(Ty::new_ref(tcx, r, ty, a_mutbl))
|
||||
}
|
||||
|
||||
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => {
|
||||
@ -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>>(
|
||||
_relation: &mut R,
|
||||
a: ty::ImplPolarity,
|
||||
b: ty::ImplPolarity,
|
||||
) -> RelateResult<'tcx, ty::ImplPolarity> {
|
||||
a: ty::PredicatePolarity,
|
||||
b: ty::PredicatePolarity,
|
||||
) -> RelateResult<'tcx, ty::PredicatePolarity> {
|
||||
if a != b { Err(TypeError::PolarityMismatch(expected_found(a, b))) } else { Ok(a) }
|
||||
}
|
||||
}
|
||||
|
@ -560,7 +560,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
let kind = match *self.kind() {
|
||||
ty::RawPtr(tm) => ty::RawPtr(tm.try_fold_with(folder)?),
|
||||
ty::RawPtr(ty, mutbl) => ty::RawPtr(ty.try_fold_with(folder)?, mutbl),
|
||||
ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?),
|
||||
ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?),
|
||||
ty::Adt(tid, args) => ty::Adt(tid, args.try_fold_with(folder)?),
|
||||
@ -607,7 +607,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||
match self.kind() {
|
||||
ty::RawPtr(ref tm) => tm.visit_with(visitor),
|
||||
ty::RawPtr(ty, _mutbl) => ty.visit_with(visitor),
|
||||
ty::Array(typ, sz) => {
|
||||
try_visit!(typ.visit_with(visitor));
|
||||
sz.visit_with(visitor)
|
||||
|
@ -1587,33 +1587,38 @@ impl<'tcx> Ty<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new(tcx, Ref(r, tm.ty, tm.mutbl))
|
||||
pub fn new_ref(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
r: Region<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
mutbl: ty::Mutability,
|
||||
) -> Ty<'tcx> {
|
||||
Ty::new(tcx, Ref(r, ty, mutbl))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
|
||||
Ty::new_ref(tcx, r, ty, hir::Mutability::Mut)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_imm_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Not })
|
||||
Ty::new_ref(tcx, r, ty, hir::Mutability::Not)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_ptr(tcx: TyCtxt<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new(tcx, RawPtr(tm))
|
||||
pub fn new_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> {
|
||||
Ty::new(tcx, ty::RawPtr(ty, mutbl))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
|
||||
Ty::new_ptr(tcx, ty, hir::Mutability::Mut)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Not })
|
||||
Ty::new_ptr(tcx, ty, hir::Mutability::Not)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -1910,7 +1915,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
pub fn is_array_slice(self) -> bool {
|
||||
match self.kind() {
|
||||
Slice(_) => true,
|
||||
RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_)),
|
||||
ty::RawPtr(ty, _) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_)),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -1964,11 +1969,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_mutable_ptr(self) -> bool {
|
||||
matches!(
|
||||
self.kind(),
|
||||
RawPtr(TypeAndMut { mutbl: hir::Mutability::Mut, .. })
|
||||
| Ref(_, _, hir::Mutability::Mut)
|
||||
)
|
||||
matches!(self.kind(), RawPtr(_, hir::Mutability::Mut) | Ref(_, _, hir::Mutability::Mut))
|
||||
}
|
||||
|
||||
/// Get the mutability of the reference or `None` when not a reference
|
||||
@ -1982,7 +1983,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_unsafe_ptr(self) -> bool {
|
||||
matches!(self.kind(), RawPtr(_))
|
||||
matches!(self.kind(), RawPtr(_, _))
|
||||
}
|
||||
|
||||
/// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer).
|
||||
@ -2038,7 +2039,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
| Uint(_)
|
||||
| FnDef(..)
|
||||
| FnPtr(_)
|
||||
| RawPtr(_)
|
||||
| RawPtr(_, _)
|
||||
| Infer(IntVar(_) | FloatVar(_))
|
||||
)
|
||||
}
|
||||
@ -2174,7 +2175,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
Some(TypeAndMut { ty: self.boxed_ty(), mutbl: hir::Mutability::Not })
|
||||
}
|
||||
Ref(_, ty, mutbl) => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }),
|
||||
RawPtr(mt) if explicit => Some(*mt),
|
||||
RawPtr(ty, mutbl) if explicit => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -2293,7 +2294,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
@ -2636,7 +2637,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
| Str
|
||||
| Array(_, _)
|
||||
| Slice(_)
|
||||
| RawPtr(_)
|
||||
| RawPtr(_, _)
|
||||
| Ref(_, _, _)
|
||||
| FnDef(_, _)
|
||||
| FnPtr(_)
|
||||
|
@ -1237,7 +1237,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
| ty::Str
|
||||
| ty::Never
|
||||
| ty::Ref(..)
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::FnDef(..)
|
||||
| ty::Error(_)
|
||||
| ty::FnPtr(_) => true,
|
||||
@ -1277,7 +1277,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
| ty::Str
|
||||
| ty::Never
|
||||
| ty::Ref(..)
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::FnDef(..)
|
||||
| ty::Error(_)
|
||||
| ty::FnPtr(_) => true,
|
||||
@ -1401,7 +1401,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true,
|
||||
|
||||
// Raw pointers use bitwise comparison.
|
||||
ty::RawPtr(_) | ty::FnPtr(_) => true,
|
||||
ty::RawPtr(_, _) | ty::FnPtr(_) => true,
|
||||
|
||||
// Floating point numbers are not `Eq`.
|
||||
ty::Float(_) => false,
|
||||
@ -1494,7 +1494,7 @@ impl<'tcx> ExplicitSelf<'tcx> {
|
||||
match *self_arg_ty.kind() {
|
||||
_ if is_self_ty(self_arg_ty) => ByValue,
|
||||
ty::Ref(region, ty, mutbl) if is_self_ty(ty) => ByReference(region, mutbl),
|
||||
ty::RawPtr(ty::TypeAndMut { ty, mutbl }) if is_self_ty(ty) => ByRawPointer(mutbl),
|
||||
ty::RawPtr(ty, mutbl) if is_self_ty(ty) => ByRawPointer(mutbl),
|
||||
ty::Adt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => ByBox,
|
||||
_ => Other,
|
||||
}
|
||||
@ -1519,7 +1519,7 @@ pub fn needs_drop_components<'tcx>(
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Char
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(..)
|
||||
| ty::Str => Ok(SmallVec::new()),
|
||||
|
||||
@ -1574,7 +1574,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
|
||||
| ty::Infer(ty::IntVar(_))
|
||||
| ty::Infer(ty::FloatVar(_))
|
||||
| ty::Str
|
||||
| ty::RawPtr(_)
|
||||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(_)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user