Merge from rustc

This commit is contained in:
Ralf Jung
2023-02-16 10:54:28 +01:00
273 changed files with 2128 additions and 7332 deletions

View File

@@ -3495,25 +3495,6 @@ dependencies = [
"serde_json",
]
[[package]]
name = "rls-data"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a58135eb039f3a3279a33779192f0ee78b56f57ae636e25cec83530e41debb99"
dependencies = [
"rls-span",
"serde",
]
[[package]]
name = "rls-span"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0eea58478fc06e15f71b03236612173a1b81e9770314edecfa664375e3e4c86"
dependencies = [
"serde",
]
[[package]]
name = "rust-demangler"
version = "0.0.1"
@@ -3965,7 +3946,6 @@ dependencies = [
"rustc_middle",
"rustc_parse",
"rustc_plugin_impl",
"rustc_save_analysis",
"rustc_session",
"rustc_span",
"rustc_target",
@@ -4625,27 +4605,6 @@ dependencies = [
"tracing",
]
[[package]]
name = "rustc_save_analysis"
version = "0.0.0"
dependencies = [
"rls-data",
"rls-span",
"rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_hir_pretty",
"rustc_lexer",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
"serde_json",
"tracing",
]
[[package]]
name = "rustc_serialize"
version = "0.0.0"

View File

@@ -139,13 +139,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::Cast(expr, ty) => {
let expr = self.lower_expr(expr);
let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast));
hir::ExprKind::Cast(expr, ty)
}
ExprKind::Type(expr, ty) => {
let expr = self.lower_expr(expr);
let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast));
hir::ExprKind::Type(expr, ty)
}
ExprKind::AddrOf(k, m, ohs) => {

View File

@@ -378,8 +378,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
});
let lowered_ty = this
.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
let lowered_ty = this.lower_ty(
ty,
&ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),
);
(trait_ref, lowered_ty)
});
@@ -458,7 +460,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span,
body: Option<&Expr>,
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
(ty, self.lower_const_body(span, body))
}
@@ -608,8 +610,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
}
ForeignItemKind::Static(t, m, _) => {
let ty =
self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
let ty = self
.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
hir::ForeignItemKind::Static(ty, *m)
}
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
@@ -679,11 +681,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself,
path,
ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
&ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy),
);
self.arena.alloc(t)
} else {
self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy))
};
let hir_id = self.lower_node_id(f.id);
self.lower_attrs(hir_id, &f.attrs);
@@ -708,7 +710,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, kind, has_default) = match &i.kind {
AssocItemKind::Const(_, ty, default) => {
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
}
@@ -746,7 +749,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
let ty = ty.as_ref().map(|x| {
this.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
this.lower_ty(
x,
&ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy),
)
});
hir::TraitItemKind::Type(
this.lower_param_bounds(
@@ -805,7 +811,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, kind) = match &i.kind {
AssocItemKind::Const(_, ty, expr) => {
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
(
hir::Generics::empty(),
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
@@ -1441,7 +1448,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir_id: self.next_id(),
bound_generic_params: self.lower_generic_params(bound_generic_params),
bounded_ty: self
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
self.lower_param_bound(
bound,
@@ -1465,9 +1472,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => {
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
lhs_ty: self
.lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
.lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
rhs_ty: self
.lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
.lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
span: self.lower_span(*span),
})
}

View File

@@ -253,7 +253,6 @@ enum ImplTraitContext {
enum ImplTraitPosition {
Path,
Variable,
Type,
Trait,
AsyncBlock,
Bound,
@@ -270,6 +269,13 @@ enum ImplTraitPosition {
FnTraitReturn,
TraitReturn,
ImplReturn,
GenericDefault,
ConstTy,
StaticTy,
AssocTy,
FieldTy,
Cast,
ImplSelf,
}
impl std::fmt::Display for ImplTraitPosition {
@@ -277,7 +283,6 @@ impl std::fmt::Display for ImplTraitPosition {
let name = match self {
ImplTraitPosition::Path => "path",
ImplTraitPosition::Variable => "variable binding",
ImplTraitPosition::Type => "type",
ImplTraitPosition::Trait => "trait",
ImplTraitPosition::AsyncBlock => "async block",
ImplTraitPosition::Bound => "bound",
@@ -294,6 +299,13 @@ impl std::fmt::Display for ImplTraitPosition {
ImplTraitPosition::FnTraitReturn => "`Fn` trait return",
ImplTraitPosition::TraitReturn => "trait method return",
ImplTraitPosition::ImplReturn => "`impl` method return",
ImplTraitPosition::GenericDefault => "generic parameter default",
ImplTraitPosition::ConstTy => "const type",
ImplTraitPosition::StaticTy => "static type",
ImplTraitPosition::AssocTy => "associated type",
ImplTraitPosition::FieldTy => "field type",
ImplTraitPosition::Cast => "cast type",
ImplTraitPosition::ImplSelf => "impl header",
};
write!(f, "{name}")
@@ -2166,7 +2178,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
GenericParamKind::Type { default, .. } => {
let kind = hir::GenericParamKind::Type {
default: default.as_ref().map(|x| {
self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
self.lower_ty(
x,
&ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
)
}),
synthetic: false,
};
@@ -2174,7 +2189,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
}
GenericParamKind::Const { ty, kw_span: _, default } => {
let ty = self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
let ty = self.lower_ty(
&ty,
&ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
);
let default = default.as_ref().map(|def| self.lower_anon_const(def));
(
hir::ParamName::Plain(self.lower_ident(param.ident)),

View File

@@ -1144,7 +1144,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
LateBoundRegionConversionTime::FnCall,
tcx.fn_sig(method_did).subst(tcx, method_substs).input(0),
)
&& infcx.can_eq(self.param_env, ty, self_ty).is_ok()
&& infcx.can_eq(self.param_env, ty, self_ty)
{
err.span_suggestion_verbose(
fn_call_span.shrink_to_lo(),
@@ -1182,8 +1182,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
let parent_did = tcx.parent(method_did);
let parent_self_ty = (tcx.def_kind(parent_did)
== rustc_hir::def::DefKind::Impl)
let parent_self_ty =
matches!(tcx.def_kind(parent_did), rustc_hir::def::DefKind::Impl { .. })
.then_some(parent_did)
.and_then(|did| match tcx.type_of(did).kind() {
ty::Adt(def, ..) => Some(def.did()),

View File

@@ -852,9 +852,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let tcx = self.infcx.tcx;
let region_parent = tcx.parent(region.def_id);
if tcx.def_kind(region_parent) != DefKind::Impl {
let DefKind::Impl { .. } = tcx.def_kind(region_parent) else {
return None;
}
};
let found = tcx
.any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));

View File

@@ -640,7 +640,8 @@ fn codegen_regular_intrinsic_call<'tcx>(
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => {
intrinsic_args!(fx, args => (); intrinsic);
let layout = fx.layout_of(substs.type_at(0));
let ty = substs.type_at(0);
let layout = fx.layout_of(ty);
if layout.abi.is_uninhabited() {
with_no_trimmed_paths!({
crate::base::codegen_panic_nounwind(
@@ -653,7 +654,10 @@ fn codegen_regular_intrinsic_call<'tcx>(
}
if intrinsic == sym::assert_zero_valid
&& !fx.tcx.permits_zero_init(fx.param_env().and(layout))
&& !fx
.tcx
.permits_zero_init(fx.param_env().and(ty))
.expect("expected to have layout during codegen")
{
with_no_trimmed_paths!({
crate::base::codegen_panic_nounwind(
@@ -669,7 +673,10 @@ fn codegen_regular_intrinsic_call<'tcx>(
}
if intrinsic == sym::assert_mem_uninitialized_valid
&& !fx.tcx.permits_uninit_init(fx.param_env().and(layout))
&& !fx
.tcx
.permits_uninit_init(fx.param_env().and(ty))
.expect("expected to have layout during codegen")
{
with_no_trimmed_paths!({
crate::base::codegen_panic_nounwind(

View File

@@ -2,9 +2,8 @@ use std::collections::hash_map::Entry::*;
use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
use rustc_hir::Node;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::{
metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
@@ -12,7 +11,7 @@ use rustc_middle::middle::exported_symbols::{
use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::Instance;
use rustc_middle::ty::{self, SymbolName, TyCtxt};
use rustc_middle::ty::{self, DefIdTree, SymbolName, TyCtxt};
use rustc_session::config::{CrateType, OomStrategy};
use rustc_target::spec::SanitizerSet;
@@ -74,33 +73,35 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
//
// As a result, if this id is an FFI item (foreign item) then we only
// let it through if it's included statically.
match tcx.hir().get_by_def_id(def_id) {
Node::ForeignItem(..) => {
tcx.native_library(def_id).map_or(false, |library| library.kind.is_statically_included()).then_some(def_id)
if let Some(parent_id) = tcx.opt_local_parent(def_id)
&& let DefKind::ForeignMod = tcx.def_kind(parent_id)
{
let library = tcx.native_library(def_id)?;
return library.kind.is_statically_included().then_some(def_id);
}
// Only consider nodes that actually have exported symbols.
Node::Item(&hir::Item {
kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn(..),
..
})
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
match tcx.def_kind(def_id) {
DefKind::Fn | DefKind::Static(_) => {}
DefKind::AssocFn if tcx.impl_of_method(def_id.to_def_id()).is_some() => {}
_ => return None,
};
let generics = tcx.generics_of(def_id);
if !generics.requires_monomorphization(tcx)
if generics.requires_monomorphization(tcx) {
return None;
}
// Functions marked with #[inline] are codegened with "internal"
// linkage and are not exported unless marked with an extern
// indicator
&& (!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
|| tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator())
if !Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
|| tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator()
{
Some(def_id)
} else {
None
}
}
_ => None,
}
})
.map(|def_id| {
// We won't link right if this symbol is stripped during LTO.
@@ -118,7 +119,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())),
export_level
);
(def_id.to_def_id(), SymbolExportInfo {
let info = SymbolExportInfo {
level: export_level,
kind: if tcx.is_static(def_id.to_def_id()) {
if codegen_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
@@ -130,8 +131,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
SymbolExportKind::Text
},
used: codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) || used,
})
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|| used,
};
(def_id.to_def_id(), info)
})
.collect();
@@ -457,9 +460,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
let target = &tcx.sess.target.llvm_target;
// WebAssembly cannot export data symbols, so reduce their export level
if target.contains("emscripten") {
if let Some(Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })) =
tcx.hir().get_if_local(sym_def_id)
{
if let DefKind::Static(_) = tcx.def_kind(sym_def_id) {
return SymbolExportLevel::Rust;
}
}

View File

@@ -674,8 +674,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let layout = bx.layout_of(ty);
let do_panic = match intrinsic {
Inhabited => layout.abi.is_uninhabited(),
ZeroValid => !bx.tcx().permits_zero_init(bx.param_env().and(layout)),
MemUninitializedValid => !bx.tcx().permits_uninit_init(bx.param_env().and(layout)),
ZeroValid => !bx
.tcx()
.permits_zero_init(bx.param_env().and(ty))
.expect("expected to have layout during codegen"),
MemUninitializedValid => !bx
.tcx()
.permits_uninit_init(bx.param_env().and(ty))
.expect("expected to have layout during codegen"),
};
Some(if do_panic {
let msg_str = with_no_visible_paths!({

View File

@@ -3,12 +3,12 @@ use rustc_attr::InstructionSetAttr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::symbol::sym;
@@ -440,12 +440,9 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxHashSet<Symbol> {
/// Checks the function annotated with `#[target_feature]` is not a safe
/// trait method implementation, reporting an error if it is.
pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
let hir_id = tcx.hir().local_def_id_to_hir_id(id);
let node = tcx.hir().get(hir_id);
if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
let parent_id = tcx.hir().get_parent_item(hir_id);
let parent_item = tcx.hir().expect_item(parent_id.def_id);
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
if let DefKind::AssocFn = tcx.def_kind(id) {
let parent_id = tcx.local_parent(id);
if let DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
tcx.sess
.struct_span_err(
attr_span,

View File

@@ -186,7 +186,7 @@ pub(super) fn op_to_const<'tcx>(
0,
),
};
let len = b.to_machine_usize(ecx).unwrap();
let len = b.to_target_usize(ecx).unwrap();
let start = start.try_into().unwrap();
let len: usize = len.try_into().unwrap();
ConstValue::Slice { data, start, end: start + len }

View File

@@ -17,7 +17,8 @@ pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
let parent_id = tcx.local_parent(def_id);
tcx.def_kind(parent_id) == DefKind::Impl && tcx.constness(parent_id) == hir::Constness::Const
matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
&& tcx.constness(parent_id) == hir::Constness::Const
}
/// Checks whether an item is considered to be `const`. If it is a constructor, it is const. If

View File

@@ -244,7 +244,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
assert_eq!(args.len(), 2);
let ptr = self.read_pointer(&args[0])?;
let target_align = self.read_scalar(&args[1])?.to_machine_usize(self)?;
let target_align = self.read_scalar(&args[1])?.to_target_usize(self)?;
if !target_align.is_power_of_two() {
throw_ub_format!("`align_offset` called with non-power-of-two align: {}", target_align);
@@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
Ok(ControlFlow::Break(()))
} else {
// Not alignable in const, return `usize::MAX`.
let usize_max = Scalar::from_machine_usize(self.machine_usize_max(), self);
let usize_max = Scalar::from_target_usize(self.target_usize_max(), self);
self.write_scalar(usize_max, dest)?;
self.return_to_block(ret)?;
Ok(ControlFlow::Break(()))
@@ -470,8 +470,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
ecx.write_scalar(Scalar::from_u8(cmp), dest)?;
}
sym::const_allocate => {
let size = ecx.read_scalar(&args[0])?.to_machine_usize(ecx)?;
let align = ecx.read_scalar(&args[1])?.to_machine_usize(ecx)?;
let size = ecx.read_scalar(&args[0])?.to_target_usize(ecx)?;
let align = ecx.read_scalar(&args[1])?.to_target_usize(ecx)?;
let align = match Align::from_bytes(align) {
Ok(a) => a,
@@ -487,8 +487,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
sym::const_deallocate => {
let ptr = ecx.read_pointer(&args[0])?;
let size = ecx.read_scalar(&args[1])?.to_machine_usize(ecx)?;
let align = ecx.read_scalar(&args[2])?.to_machine_usize(ecx)?;
let size = ecx.read_scalar(&args[1])?.to_target_usize(ecx)?;
let align = ecx.read_scalar(&args[2])?.to_target_usize(ecx)?;
let size = Size::from_bytes(size);
let align = match Align::from_bytes(align) {

View File

@@ -155,7 +155,7 @@ pub(crate) fn deref_mir_constant<'tcx>(
// In case of unsized types, figure out the real type behind.
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
ty::Str => bug!("there's no sized equivalent of a `str`"),
ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_target_usize(&tcx).unwrap()),
_ => bug!(
"type {} should not have metadata, but had {:?}",
mplace.layout.ty,

View File

@@ -239,7 +239,7 @@ fn create_pointee_place<'tcx>(
MPlaceTy::from_aligned_ptr_with_meta(
ptr.into(),
layout,
MemPlaceMeta::Meta(Scalar::from_machine_usize(num_elems as u64, &tcx)),
MemPlaceMeta::Meta(Scalar::from_target_usize(num_elems as u64, &tcx)),
)
} else {
create_mplace_from_layout(ecx, ty)
@@ -355,7 +355,7 @@ fn valtree_into_mplace<'tcx>(
let imm = match inner_ty.kind() {
ty::Slice(_) | ty::Str => {
let len = valtree.unwrap_branch().len();
let len_scalar = Scalar::from_machine_usize(len as u64, &tcx);
let len_scalar = Scalar::from_target_usize(len as u64, &tcx);
Immediate::ScalarPair(
Scalar::from_maybe_pointer((*pointee_place).ptr, &tcx),
@@ -426,7 +426,7 @@ fn valtree_into_mplace<'tcx>(
place
.offset_with_meta(
offset,
MemPlaceMeta::Meta(Scalar::from_machine_usize(
MemPlaceMeta::Meta(Scalar::from_target_usize(
num_elems as u64,
&tcx,
)),

View File

@@ -231,7 +231,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// First cast to usize.
let scalar = src.to_scalar();
let addr = self.cast_from_int_like(scalar, src.layout, self.tcx.types.usize)?;
let addr = addr.to_machine_usize(self)?;
let addr = addr.to_target_usize(self)?;
// Then turn address into pointer.
let ptr = M::ptr_from_addr_cast(&self, addr)?;

View File

@@ -639,7 +639,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
ty::Slice(_) | ty::Str => {
let len = metadata.unwrap_meta().to_machine_usize(self)?;
let len = metadata.unwrap_meta().to_target_usize(self)?;
let elem = layout.field(self, 0);
// Make sure the slice is not too big.

View File

@@ -71,7 +71,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
sym::pref_align_of => {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
ConstValue::from_machine_usize(layout.align.pref.bytes(), &tcx)
ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx)
}
sym::type_id => {
ensure_monomorphic_enough(tcx, tp_ty)?;
@@ -79,7 +79,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
}
sym::variant_count => match tp_ty.kind() {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
ty::Adt(adt, _) => ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx),
ty::Adt(adt, _) => ConstValue::from_target_usize(adt.variants().len() as u64, &tcx),
ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
throw_inval!(TooGeneric)
}
@@ -104,7 +104,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
| ty::GeneratorWitnessMIR(_, _)
| ty::Never
| ty::Tuple(_)
| ty::Error(_) => ConstValue::from_machine_usize(0u64, &tcx),
| ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx),
},
other => bug!("`{}` is not a zero arg intrinsic", other),
})
@@ -156,7 +156,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
_ => bug!(),
};
self.write_scalar(Scalar::from_machine_usize(result, self), dest)?;
self.write_scalar(Scalar::from_target_usize(result, self), dest)?;
}
sym::pref_align_of
@@ -302,7 +302,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
sym::offset => {
let ptr = self.read_pointer(&args[0])?;
let offset_count = self.read_machine_isize(&args[1])?;
let offset_count = self.read_target_isize(&args[1])?;
let pointee_ty = substs.type_at(0);
let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
@@ -310,7 +310,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
sym::arith_offset => {
let ptr = self.read_pointer(&args[0])?;
let offset_count = self.read_machine_isize(&args[1])?;
let offset_count = self.read_target_isize(&args[1])?;
let pointee_ty = substs.type_at(0);
let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
@@ -376,7 +376,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// The signed form of the intrinsic allows this. If we interpret the
// difference as isize, we'll get the proper signed difference. If that
// seems *positive*, they were more than isize::MAX apart.
let dist = val.to_machine_isize(self)?;
let dist = val.to_target_isize(self)?;
if dist >= 0 {
throw_ub_format!(
"`{}` called when first pointer is too far before second",
@@ -386,7 +386,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
dist
} else {
// b >= a
let dist = val.to_machine_isize(self)?;
let dist = val.to_target_isize(self)?;
// If converting to isize produced a *negative* result, we had an overflow
// because they were more than isize::MAX apart.
if dist < 0 {
@@ -411,10 +411,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Perform division by size to compute return value.
let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
assert!(0 <= dist && dist <= self.machine_isize_max());
assert!(0 <= dist && dist <= self.target_isize_max());
usize_layout
} else {
assert!(self.machine_isize_min() <= dist && dist <= self.machine_isize_max());
assert!(self.target_isize_min() <= dist && dist <= self.target_isize_max());
isize_layout
};
let pointee_layout = self.layout_of(substs.type_at(0))?;
@@ -448,7 +448,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
if intrinsic_name == sym::assert_zero_valid {
let should_panic = !self.tcx.permits_zero_init(self.param_env.and(layout));
let should_panic = !self
.tcx
.permits_zero_init(self.param_env.and(ty))
.map_err(|_| err_inval!(TooGeneric))?;
if should_panic {
M::abort(
@@ -462,7 +465,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
if intrinsic_name == sym::assert_mem_uninitialized_valid {
let should_panic = !self.tcx.permits_uninit_init(self.param_env.and(layout));
let should_panic = !self
.tcx
.permits_uninit_init(self.param_env.and(ty))
.map_err(|_| err_inval!(TooGeneric))?;
if should_panic {
M::abort(
@@ -525,12 +531,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
sym::vtable_size => {
let ptr = self.read_pointer(&args[0])?;
let (size, _align) = self.get_vtable_size_and_align(ptr)?;
self.write_scalar(Scalar::from_machine_usize(size.bytes(), self), dest)?;
self.write_scalar(Scalar::from_target_usize(size.bytes(), self), dest)?;
}
sym::vtable_align => {
let ptr = self.read_pointer(&args[0])?;
let (_size, align) = self.get_vtable_size_and_align(ptr)?;
self.write_scalar(Scalar::from_machine_usize(align.bytes(), self), dest)?;
self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
}
_ => return Ok(false),
@@ -669,10 +675,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
nonoverlapping: bool,
) -> InterpResult<'tcx> {
let count = self.read_machine_usize(&count)?;
let count = self.read_target_usize(&count)?;
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
let (size, align) = (layout.size, layout.align.abi);
// `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
// `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
// but no actual allocation can be big enough for the difference to be noticeable.
let size = size.checked_mul(count, self).ok_or_else(|| {
err_ub_format!(
@@ -697,9 +703,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let dst = self.read_pointer(&dst)?;
let byte = self.read_scalar(&byte)?.to_u8()?;
let count = self.read_machine_usize(&count)?;
let count = self.read_target_usize(&count)?;
// `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
// `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
// but no actual allocation can be big enough for the difference to be noticeable.
let len = layout
.size

View File

@@ -425,7 +425,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
throw_ub!(PointerOutOfBounds {
alloc_id,
alloc_size,
ptr_offset: self.machine_usize_to_isize(offset.bytes()),
ptr_offset: self.target_usize_to_isize(offset.bytes()),
ptr_size: size,
msg,
})

View File

@@ -52,7 +52,7 @@ impl<Prov: Provenance> Immediate<Prov> {
}
pub fn new_slice(val: Scalar<Prov>, len: u64, cx: &impl HasDataLayout) -> Self {
Immediate::ScalarPair(val, Scalar::from_machine_usize(len, cx))
Immediate::ScalarPair(val, Scalar::from_target_usize(len, cx))
}
pub fn new_dyn_trait(
@@ -414,12 +414,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.read_scalar(op)?.to_pointer(self)
}
/// Read a pointer-sized unsigned integer from a place.
pub fn read_machine_usize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, u64> {
self.read_scalar(op)?.to_machine_usize(self)
pub fn read_target_usize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, u64> {
self.read_scalar(op)?.to_target_usize(self)
}
/// Read a pointer-sized signed integer from a place.
pub fn read_machine_isize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, i64> {
self.read_scalar(op)?.to_machine_isize(self)
pub fn read_target_isize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, i64> {
self.read_scalar(op)?.to_target_isize(self)
}
/// Turn the wide MPlace into a string (must already be dereferenced!)

View File

@@ -229,7 +229,7 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
if self.layout.is_unsized() {
// We need to consult `meta` metadata
match self.layout.ty.kind() {
ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_machine_usize(cx),
ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_target_usize(cx),
_ => bug!("len not supported on unsized type {:?}", self.layout.ty),
}
} else {
@@ -756,7 +756,7 @@ where
mutbl: Mutability,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl)?;
let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self);
let meta = Scalar::from_target_usize(u64::try_from(str.len()).unwrap(), self);
let mplace = MemPlace { ptr: ptr.into(), meta: MemPlaceMeta::Meta(meta) };
let ty = self.tcx.mk_ref(

View File

@@ -319,7 +319,7 @@ where
// implement this.
ty::Array(inner, _) => (MemPlaceMeta::None, self.tcx.mk_array(*inner, inner_len)),
ty::Slice(..) => {
let len = Scalar::from_machine_usize(inner_len, self);
let len = Scalar::from_target_usize(inner_len, self);
(MemPlaceMeta::Meta(len), base.layout.ty)
}
_ => {
@@ -363,7 +363,7 @@ where
Index(local) => {
let layout = self.layout_of(self.tcx.types.usize)?;
let n = self.local_to_op(self.frame(), local, Some(layout))?;
let n = self.read_machine_usize(&n)?;
let n = self.read_target_usize(&n)?;
self.place_index(base, n)?
}
ConstantIndex { offset, min_length, from_end } => {
@@ -392,7 +392,7 @@ where
Index(local) => {
let layout = self.layout_of(self.tcx.types.usize)?;
let n = self.local_to_op(self.frame(), local, Some(layout))?;
let n = self.read_machine_usize(&n)?;
let n = self.read_target_usize(&n)?;
self.operand_index(base, n)?
}
ConstantIndex { offset, min_length, from_end } => {

View File

@@ -242,7 +242,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let src = self.eval_place(place)?;
let op = self.place_to_op(&src)?;
let len = op.len(self)?;
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
self.write_scalar(Scalar::from_target_usize(len, self), &dest)?;
}
Ref(_, borrow_kind, place) => {
@@ -297,7 +297,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
mir::NullOp::SizeOf => layout.size.bytes(),
mir::NullOp::AlignOf => layout.align.abi.bytes(),
};
self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
self.write_scalar(Scalar::from_target_usize(val, self), &dest)?;
}
ShallowInitBox(ref operand, _) => {

View File

@@ -348,7 +348,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// FIXME: check if the type/trait match what ty::Dynamic says?
}
ty::Slice(..) | ty::Str => {
let _len = meta.unwrap_meta().to_machine_usize(self.ecx)?;
let _len = meta.unwrap_meta().to_target_usize(self.ecx)?;
// We do not check that `len * elem_size <= isize::MAX`:
// that is only required for references, and there it falls out of the
// "dereferenceable" check performed by Stacked Borrows.

View File

@@ -59,11 +59,8 @@ pub fn provide(providers: &mut Providers) {
const_eval::deref_mir_constant(tcx, param_env, value)
};
providers.permits_uninit_init = |tcx, param_env_and_ty| {
let (param_env, ty) = param_env_and_ty.into_parts();
util::might_permit_raw_init(tcx, param_env, ty, InitKind::UninitMitigated0x01Fill)
};
providers.permits_zero_init = |tcx, param_env_and_ty| {
let (param_env, ty) = param_env_and_ty.into_parts();
util::might_permit_raw_init(tcx, param_env, ty, InitKind::Zero)
util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::UninitMitigated0x01Fill)
};
providers.permits_zero_init =
|tcx, param_env_and_ty| util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::Zero);
}

View File

@@ -1,5 +1,5 @@
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::{ParamEnv, TyCtxt};
use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout};
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_session::Limit;
use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
@@ -20,15 +20,14 @@ use crate::interpret::{InterpCx, MemoryKind, OpTy};
/// to the full uninit check).
pub fn might_permit_raw_init<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
ty: TyAndLayout<'tcx>,
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
kind: InitKind,
) -> bool {
) -> Result<bool, LayoutError<'tcx>> {
if tcx.sess.opts.unstable_opts.strict_init_checks {
might_permit_raw_init_strict(ty, tcx, kind)
might_permit_raw_init_strict(tcx.layout_of(param_env_and_ty)?, tcx, kind)
} else {
let layout_cx = LayoutCx { tcx, param_env };
might_permit_raw_init_lax(ty, &layout_cx, kind)
let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
might_permit_raw_init_lax(tcx.layout_of(param_env_and_ty)?, &layout_cx, kind)
}
}
@@ -38,7 +37,7 @@ fn might_permit_raw_init_strict<'tcx>(
ty: TyAndLayout<'tcx>,
tcx: TyCtxt<'tcx>,
kind: InitKind,
) -> bool {
) -> Result<bool, LayoutError<'tcx>> {
let machine = CompileTimeInterpreter::new(
Limit::new(0),
/*can_access_statics:*/ false,
@@ -65,7 +64,7 @@ fn might_permit_raw_init_strict<'tcx>(
// This does *not* actually check that references are dereferenceable, but since all types that
// require dereferenceability also require non-null, we don't actually get any false negatives
// due to this.
cx.validate_operand(&ot).is_ok()
Ok(cx.validate_operand(&ot).is_ok())
}
/// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for
@@ -74,7 +73,7 @@ fn might_permit_raw_init_lax<'tcx>(
this: TyAndLayout<'tcx>,
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
init_kind: InitKind,
) -> bool {
) -> Result<bool, LayoutError<'tcx>> {
let scalar_allows_raw_init = move |s: Scalar| -> bool {
match init_kind {
InitKind::Zero => {
@@ -103,20 +102,20 @@ fn might_permit_raw_init_lax<'tcx>(
};
if !valid {
// This is definitely not okay.
return false;
return Ok(false);
}
// Special magic check for references and boxes (i.e., special pointer types).
if let Some(pointee) = this.ty.builtin_deref(false) {
let pointee = cx.layout_of(pointee.ty).expect("need to be able to compute layouts");
let pointee = cx.layout_of(pointee.ty)?;
// We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied.
if pointee.align.abi.bytes() > 1 {
// 0x01-filling is not aligned.
return false;
return Ok(false);
}
if pointee.size.bytes() > 0 {
// A 'fake' integer pointer is not sufficiently dereferenceable.
return false;
return Ok(false);
}
}
@@ -129,9 +128,9 @@ fn might_permit_raw_init_lax<'tcx>(
}
FieldsShape::Arbitrary { offsets, .. } => {
for idx in 0..offsets.len() {
if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind) {
if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind)? {
// We found a field that is unhappy with this kind of initialization.
return false;
return Ok(false);
}
}
}
@@ -148,5 +147,5 @@ fn might_permit_raw_init_lax<'tcx>(
}
}
true
Ok(true)
}

View File

@@ -22,7 +22,6 @@ rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" }
rustc_parse = { path = "../rustc_parse" }
rustc_plugin_impl = { path = "../rustc_plugin_impl" }
rustc_save_analysis = { path = "../rustc_save_analysis" }
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
rustc_session = { path = "../rustc_session" }
rustc_error_codes = { path = "../rustc_error_codes" }

View File

@@ -25,13 +25,10 @@ use rustc_data_structures::sync::SeqCst;
use rustc_errors::registry::{InvalidErrorCode, Registry};
use rustc_errors::{ErrorGuaranteed, PResult, TerminalUrl};
use rustc_feature::find_gated_cfg;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
use rustc_interface::{interface, Queries};
use rustc_lint::LintStore;
use rustc_metadata::locator;
use rustc_save_analysis as save;
use rustc_save_analysis::DumpHandler;
use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths};
use rustc_session::cstore::MetadataLoader;
@@ -343,22 +340,7 @@ fn run_compiler(
return early_exit();
}
queries.global_ctxt()?.enter(|tcx| {
let result = tcx.analysis(());
if sess.opts.unstable_opts.save_analysis {
let crate_name = tcx.crate_name(LOCAL_CRATE);
sess.time("save_analysis", || {
save::process_crate(
tcx,
crate_name,
&sess.io.input,
None,
DumpHandler::new(sess.io.output_dir.as_deref(), crate_name),
)
});
}
result
})?;
queries.global_ctxt()?.enter(|tcx| tcx.analysis(()))?;
if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
return early_exit();

View File

@@ -140,6 +140,18 @@ infer_lifetime_param_suggestion_elided = each elided lifetime in input position
infer_region_explanation = {$pref_kind ->
*[should_not_happen] [{$pref_kind}]
[ref_valid_for] ...the reference is valid for
[content_valid_for] ...but the borrowed content is only valid for
[type_obj_valid_for] object type is valid for
[source_pointer_valid_for] source pointer is only valid for
[type_satisfy] type must satisfy
[type_outlive] type must outlive
[lf_param_instantiated_with] lifetime parameter instantiated with
[lf_param_must_outlive] but lifetime parameter must outlive
[lf_instantiated_with] lifetime instantiated with
[lf_must_outlive] but lifetime must outlive
[pointer_valid_for] the pointer is valid for
[data_valid_for] but the referenced data is only valid for
[empty] {""}
}{$pref_kind ->
[empty] {""}
@@ -148,7 +160,6 @@ infer_region_explanation = {$pref_kind ->
*[should_not_happen] [{$desc_kind}]
[restatic] the static lifetime
[revar] lifetime {$desc_arg}
[as_defined] the lifetime `{$desc_arg}` as defined here
[as_defined_anon] the anonymous lifetime as defined here
[defined_here] the anonymous lifetime defined here
@@ -158,8 +169,16 @@ infer_region_explanation = {$pref_kind ->
*[should_not_happen] [{$suff_kind}]
[empty]{""}
[continues] ...
[req_by_binding] {" "}as required by this binding
}
infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
infer_fullfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
infer_lf_bound_not_satisfied = lifetime bound not satisfied
infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
infer_mismatched_static_lifetime = incompatible lifetime on type
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
@@ -308,3 +327,21 @@ infer_ril_introduced_here = `'static` requirement introduced here
infer_ril_introduced_by = requirement introduced by this return type
infer_ril_because_of = because of this returned expression
infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
infer_where_remove = remove the `where` clause
infer_where_copy_predicates = copy the `where` clause predicates from the trait
infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
infer_srs_remove = consider removing this semicolon
infer_srs_add = consider returning the local binding `{$ident}`
infer_srs_add_one = consider returning one of these bindings
infer_await_both_futures = consider `await`ing on both `Future`s
infer_await_future = consider `await`ing on the `Future`
infer_await_note = calling an async function returns a future
infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
infer_prlf_defined_without_sub = the lifetime defined here...
infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here
infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)

View File

@@ -1 +0,0 @@
save_analysis_could_not_open = Could not open `{$file_name}`: `{$err}`

View File

@@ -67,7 +67,6 @@ fluent_messages! {
privacy => "../locales/en-US/privacy.ftl",
query_system => "../locales/en-US/query_system.ftl",
resolve => "../locales/en-US/resolve.ftl",
save_analysis => "../locales/en-US/save_analysis.ftl",
session => "../locales/en-US/session.ftl",
symbol_mangling => "../locales/en-US/symbol_mangling.ftl",
trait_selection => "../locales/en-US/trait_selection.ftl",

View File

@@ -116,7 +116,9 @@ pub enum DefKind {
LifetimeParam,
/// A use of `global_asm!`.
GlobalAsm,
Impl,
Impl {
of_trait: bool,
},
Closure,
Generator,
}
@@ -155,7 +157,7 @@ impl DefKind {
DefKind::AnonConst => "constant expression",
DefKind::InlineConst => "inline constant",
DefKind::Field => "field",
DefKind::Impl => "implementation",
DefKind::Impl { .. } => "implementation",
DefKind::Closure => "closure",
DefKind::Generator => "generator",
DefKind::ExternCrate => "extern crate",
@@ -171,7 +173,7 @@ impl DefKind {
| DefKind::AssocFn
| DefKind::Enum
| DefKind::OpaqueTy
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::Use
| DefKind::InlineConst
| DefKind::ExternCrate => "an",
@@ -216,7 +218,7 @@ impl DefKind {
| DefKind::Use
| DefKind::ForeignMod
| DefKind::GlobalAsm
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::ImplTraitPlaceholder => None,
}
}
@@ -255,7 +257,7 @@ impl DefKind {
| DefKind::ForeignMod
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::Field
| DefKind::TyParam
| DefKind::ConstParam

View File

@@ -116,7 +116,7 @@ impl Target {
DefKind::Union => Target::Union,
DefKind::Trait => Target::Trait,
DefKind::TraitAlias => Target::TraitAlias,
DefKind::Impl => Target::Impl,
DefKind::Impl { .. } => Target::Impl,
_ => panic!("impossible case reached"),
}
}

View File

@@ -1970,7 +1970,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
) = &qself.kind {
// If the path segment already has type params, we want to overwrite
// them.
match &path.segments[..] {
match &path.segments {
// `segment` is the previous to last element on the path,
// which would normally be the `enum` itself, while the last
// `_` `PathSegment` corresponds to the variant.
@@ -2232,7 +2232,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.erase_regions(impl_.self_ty()),
tcx.erase_regions(qself_ty),
)
.is_ok()
})
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
})
@@ -2671,7 +2670,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// `Self` in trait or type alias.
assert_eq!(opt_self_ty, None);
self.prohibit_generics(path.segments.iter(), |err| {
if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments[..] {
if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments {
err.span_suggestion_verbose(
ident.span.shrink_to_hi().to(args.span_ext),
"the `Self` type doesn't accept type parameters",

View File

@@ -21,7 +21,9 @@ use rustc_middle::middle::stability::EvalResult;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_middle::ty::{
self, AdtDef, DefIdTree, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
use rustc_span::{self, Span};
@@ -174,16 +176,8 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
Ok(l) => l,
// Foreign statics that overflow their allowed size should emit an error
Err(LayoutError::SizeOverflow(_))
if {
let node = tcx.hir().get_by_def_id(def_id);
matches!(
node,
hir::Node::ForeignItem(hir::ForeignItem {
kind: hir::ForeignItemKind::Static(..),
..
})
)
} =>
if matches!(tcx.def_kind(def_id), DefKind::Static(_)
if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
{
tcx.sess
.struct_span_err(span, "extern static is too large for the current architecture")
@@ -215,7 +209,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
let item = tcx.hir().item(id);
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
tcx.sess.delay_span_bug(tcx.hir().span(id.hir_id()), "expected opaque item");
tcx.sess.delay_span_bug(item.span, "expected opaque item");
return;
};
@@ -529,45 +523,34 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_enum(tcx, id.owner_id.def_id);
}
DefKind::Fn => {} // entirely within check_item_body
DefKind::Impl => {
let it = tcx.hir().item(id);
let hir::ItemKind::Impl(impl_) = it.kind else { return };
debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id);
if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) {
DefKind::Impl { of_trait } => {
if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(id.owner_id) {
check_impl_items_against_trait(
tcx,
it.span,
it.owner_id.def_id,
id.owner_id.def_id,
impl_trait_ref.subst_identity(),
&impl_.items,
);
check_on_unimplemented(tcx, it);
check_on_unimplemented(tcx, id);
}
}
DefKind::Trait => {
let it = tcx.hir().item(id);
let hir::ItemKind::Trait(_, _, _, _, items) = it.kind else {
return;
};
check_on_unimplemented(tcx, it);
let assoc_items = tcx.associated_items(id.owner_id);
check_on_unimplemented(tcx, id);
for item in items.iter() {
let item = tcx.hir().trait_item(item.id);
match &item.kind {
hir::TraitItemKind::Fn(sig, _) => {
let abi = sig.header.abi;
fn_maybe_err(tcx, item.ident.span, abi);
for assoc_item in assoc_items.in_definition_order() {
match assoc_item.kind {
ty::AssocKind::Fn => {
let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi();
fn_maybe_err(tcx, assoc_item.ident(tcx).span, abi);
}
hir::TraitItemKind::Type(.., Some(default)) => {
let assoc_item = tcx.associated_item(item.owner_id);
ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
let trait_substs =
InternalSubsts::identity_for_item(tcx, it.owner_id.to_def_id());
InternalSubsts::identity_for_item(tcx, id.owner_id.to_def_id());
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
tcx,
assoc_item,
assoc_item,
default.span,
tcx.mk_trait_ref(it.owner_id.to_def_id(), trait_substs),
tcx.mk_trait_ref(id.owner_id.to_def_id(), trait_substs),
);
}
_ => {}
@@ -679,7 +662,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
}
}
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: hir::ItemId) {
// an error would be reported if this fails.
let _ = OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
}
@@ -689,7 +672,7 @@ pub(super) fn check_specialization_validity<'tcx>(
trait_def: &ty::TraitDef,
trait_item: &ty::AssocItem,
impl_id: DefId,
impl_item: &hir::ImplItemRef,
impl_item: DefId,
) {
let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) else { return };
let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| {
@@ -735,10 +718,8 @@ pub(super) fn check_specialization_validity<'tcx>(
fn check_impl_items_against_trait<'tcx>(
tcx: TyCtxt<'tcx>,
full_impl_span: Span,
impl_id: LocalDefId,
impl_trait_ref: ty::TraitRef<'tcx>,
impl_item_refs: &[hir::ImplItemRef],
) {
// If the trait reference itself is erroneous (so the compilation is going
// to fail), skip checking the items here -- the `impl_item` table in `tcx`
@@ -747,12 +728,14 @@ fn check_impl_items_against_trait<'tcx>(
return;
}
let impl_item_refs = tcx.associated_item_def_ids(impl_id);
// Negative impls are not expected to have any items
match tcx.impl_polarity(impl_id) {
ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
ty::ImplPolarity::Negative => {
if let [first_item_ref, ..] = impl_item_refs {
let first_item_span = tcx.hir().impl_item(first_item_ref.id).span;
let first_item_span = tcx.def_span(first_item_ref);
struct_span_err!(
tcx.sess,
first_item_span,
@@ -767,43 +750,27 @@ fn check_impl_items_against_trait<'tcx>(
let trait_def = tcx.trait_def(impl_trait_ref.def_id);
for impl_item in impl_item_refs {
let ty_impl_item = tcx.associated_item(impl_item.id.owner_id);
for &impl_item in impl_item_refs {
let ty_impl_item = tcx.associated_item(impl_item);
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
tcx.associated_item(trait_item_id)
} else {
// Checked in `associated_item`.
tcx.sess.delay_span_bug(impl_item.span, "missing associated item in trait");
tcx.sess.delay_span_bug(tcx.def_span(impl_item), "missing associated item in trait");
continue;
};
let impl_item_full = tcx.hir().impl_item(impl_item.id);
match impl_item_full.kind {
hir::ImplItemKind::Const(..) => {
match ty_impl_item.kind {
ty::AssocKind::Const => {
let _ = tcx.compare_impl_const((
impl_item.id.owner_id.def_id,
impl_item.expect_local(),
ty_impl_item.trait_item_def_id.unwrap(),
));
}
hir::ImplItemKind::Fn(..) => {
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
compare_impl_method(
tcx,
&ty_impl_item,
&ty_trait_item,
impl_trait_ref,
opt_trait_span,
);
ty::AssocKind::Fn => {
compare_impl_method(tcx, &ty_impl_item, &ty_trait_item, impl_trait_ref);
}
hir::ImplItemKind::Type(impl_ty) => {
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
compare_impl_ty(
tcx,
&ty_impl_item,
impl_ty.span,
&ty_trait_item,
impl_trait_ref,
opt_trait_span,
);
ty::AssocKind::Type => {
compare_impl_ty(tcx, &ty_impl_item, &ty_trait_item, impl_trait_ref);
}
}
@@ -838,6 +805,8 @@ fn check_impl_items_against_trait<'tcx>(
.map_or(false, |node_item| !node_item.defining_node.is_from_trait());
if !is_implemented_here {
let full_impl_span =
tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
match tcx.eval_default_body_stability(trait_item_id, full_impl_span) {
EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable(
tcx,
@@ -864,6 +833,8 @@ fn check_impl_items_against_trait<'tcx>(
}
if !missing_items.is_empty() {
let full_impl_span =
tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
missing_items_err(tcx, tcx.def_span(impl_id), &missing_items, full_impl_span);
}

View File

@@ -33,7 +33,6 @@ use std::iter;
/// # Parameters
///
/// - `impl_m`: type of the method we are checking
/// - `impl_m_span`: span to use for reporting errors
/// - `trait_m`: the method in the trait
/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
pub(super) fn compare_impl_method<'tcx>(
@@ -41,23 +40,19 @@ pub(super) fn compare_impl_method<'tcx>(
impl_m: &ty::AssocItem,
trait_m: &ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
trait_item_span: Option<Span>,
) {
debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
let impl_m_span = tcx.def_span(impl_m.def_id);
let _: Result<_, ErrorGuaranteed> = try {
compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)?;
compare_number_of_generics(tcx, impl_m, trait_m, trait_item_span, false)?;
compare_self_type(tcx, impl_m, trait_m, impl_trait_ref)?;
compare_number_of_generics(tcx, impl_m, trait_m, false)?;
compare_generic_param_kinds(tcx, impl_m, trait_m, false)?;
compare_number_of_method_arguments(tcx, impl_m, impl_m_span, trait_m, trait_item_span)?;
compare_number_of_method_arguments(tcx, impl_m, trait_m)?;
compare_synthetic_generics(tcx, impl_m, trait_m)?;
compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span)?;
compare_asyncness(tcx, impl_m, trait_m)?;
compare_method_predicate_entailment(
tcx,
impl_m,
impl_m_span,
trait_m,
impl_trait_ref,
CheckImpliedWfMode::Check,
@@ -131,11 +126,10 @@ pub(super) fn compare_impl_method<'tcx>(
///
/// Finally we register each of these predicates as an obligation and check that
/// they hold.
#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
#[instrument(level = "debug", skip(tcx, impl_trait_ref))]
fn compare_method_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: &ty::AssocItem,
impl_m_span: Span,
trait_m: &ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
check_implied_wf: CheckImpliedWfMode,
@@ -148,6 +142,7 @@ fn compare_method_predicate_entailment<'tcx>(
// FIXME(@lcnr): remove that after removing `cause.body_id` from
// obligations.
let impl_m_def_id = impl_m.def_id.expect_local();
let impl_m_span = tcx.def_span(impl_m_def_id);
let cause = ObligationCause::new(
impl_m_span,
impl_m_def_id,
@@ -315,7 +310,6 @@ fn compare_method_predicate_entailment<'tcx>(
return compare_method_predicate_entailment(
tcx,
impl_m,
impl_m_span,
trait_m,
impl_trait_ref,
CheckImpliedWfMode::Skip,
@@ -353,7 +347,6 @@ fn compare_method_predicate_entailment<'tcx>(
return compare_method_predicate_entailment(
tcx,
impl_m,
impl_m_span,
trait_m,
impl_trait_ref,
CheckImpliedWfMode::Skip,
@@ -535,9 +528,7 @@ enum CheckImpliedWfMode {
fn compare_asyncness<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: &ty::AssocItem,
impl_m_span: Span,
trait_m: &ty::AssocItem,
trait_item_span: Option<Span>,
) -> Result<(), ErrorGuaranteed> {
if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
@@ -549,9 +540,9 @@ fn compare_asyncness<'tcx>(
}
_ => {
return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
span: impl_m_span,
span: tcx.def_span(impl_m.def_id),
method_name: trait_m.name,
trait_item_span,
trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
}));
}
};
@@ -606,7 +597,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during substitution later.
compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
compare_number_of_generics(tcx, impl_m, trait_m, true)?;
compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
@@ -1094,7 +1085,6 @@ fn extract_spans_for_error_reporting<'tcx>(
fn compare_self_type<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: &ty::AssocItem,
impl_m_span: Span,
trait_m: &ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
@@ -1116,7 +1106,7 @@ fn compare_self_type<'tcx>(
let infcx = tcx.infer_ctxt().build();
let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok();
let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);
match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
ExplicitSelf::ByValue => "self".to_owned(),
ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
@@ -1130,6 +1120,7 @@ fn compare_self_type<'tcx>(
(false, true) => {
let self_descr = self_string(impl_m);
let impl_m_span = tcx.def_span(impl_m.def_id);
let mut err = struct_span_err!(
tcx.sess,
impl_m_span,
@@ -1149,6 +1140,7 @@ fn compare_self_type<'tcx>(
(true, false) => {
let self_descr = self_string(trait_m);
let impl_m_span = tcx.def_span(impl_m.def_id);
let mut err = struct_span_err!(
tcx.sess,
impl_m_span,
@@ -1196,7 +1188,6 @@ fn compare_number_of_generics<'tcx>(
tcx: TyCtxt<'tcx>,
impl_: &ty::AssocItem,
trait_: &ty::AssocItem,
trait_span: Option<Span>,
delay: bool,
) -> Result<(), ErrorGuaranteed> {
let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
@@ -1256,6 +1247,7 @@ fn compare_number_of_generics<'tcx>(
.collect();
(Some(arg_spans), impl_trait_spans)
} else {
let trait_span = tcx.hir().span_if_local(trait_.def_id);
(trait_span.map(|s| vec![s]), vec![])
};
@@ -1338,9 +1330,7 @@ fn compare_number_of_generics<'tcx>(
fn compare_number_of_method_arguments<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: &ty::AssocItem,
impl_m_span: Span,
trait_m: &ty::AssocItem,
trait_item_span: Option<Span>,
) -> Result<(), ErrorGuaranteed> {
let impl_m_fty = tcx.fn_sig(impl_m.def_id);
let trait_m_fty = tcx.fn_sig(trait_m.def_id);
@@ -1362,7 +1352,7 @@ fn compare_number_of_method_arguments<'tcx>(
}
})
})
.or(trait_item_span);
.or_else(|| tcx.hir().span_if_local(trait_m.def_id));
let (impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
let pos = impl_number_args.saturating_sub(1);
@@ -1377,7 +1367,7 @@ fn compare_number_of_method_arguments<'tcx>(
arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
}
})
.unwrap_or(impl_m_span);
.unwrap_or_else(|| tcx.def_span(impl_m.def_id));
let mut err = struct_span_err!(
tcx.sess,
@@ -1747,22 +1737,16 @@ pub(super) fn compare_impl_const_raw(
pub(super) fn compare_impl_ty<'tcx>(
tcx: TyCtxt<'tcx>,
impl_ty: &ty::AssocItem,
impl_ty_span: Span,
trait_ty: &ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
trait_item_span: Option<Span>,
) {
debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
let _: Result<(), ErrorGuaranteed> = try {
compare_number_of_generics(tcx, impl_ty, trait_ty, trait_item_span, false)?;
compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
let sp = tcx.def_span(impl_ty.def_id);
compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?;
check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)?;
compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?;
};
}
@@ -1771,7 +1755,6 @@ pub(super) fn compare_impl_ty<'tcx>(
fn compare_type_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
impl_ty: &ty::AssocItem,
impl_ty_span: Span,
trait_ty: &ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
@@ -1808,6 +1791,7 @@ fn compare_type_predicate_entailment<'tcx>(
debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
let impl_ty_span = tcx.def_span(impl_ty_def_id);
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id);
let param_env = ty::ParamEnv::new(
tcx.intern_predicates(&hybrid_preds.predicates),
@@ -1873,7 +1857,6 @@ pub(super) fn check_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ty: &ty::AssocItem,
impl_ty: &ty::AssocItem,
impl_ty_span: Span,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
// Given
@@ -2009,8 +1992,15 @@ pub(super) fn check_type_bounds<'tcx>(
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
let assumed_wf_types =
ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty.def_id.expect_local());
let impl_ty_span = match tcx.hir().get_by_def_id(impl_ty_def_id) {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(_, Some(ty)),
..
}) => ty.span,
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
_ => bug!(),
};
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
let normalize_cause = ObligationCause::new(
impl_ty_span,

View File

@@ -414,7 +414,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check that sym actually points to a function. Later passes
// depend on this.
hir::InlineAsmOperand::SymFn { anon_const } => {
let ty = self.tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
let ty = self.tcx.type_of(anon_const.def_id);
match ty.kind() {
ty::Never | ty::Error(_) => {}
ty::FnDef(..) => {}
@@ -422,7 +422,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let mut err =
self.tcx.sess.struct_span_err(*op_sp, "invalid `sym` operand");
err.span_label(
self.tcx.hir().span(anon_const.body.hir_id),
self.tcx.def_span(anon_const.def_id),
&format!("is {} `{}`", ty.kind().article(), ty),
);
err.help("`sym` operands must refer to either a function or a static");

View File

@@ -75,7 +75,6 @@ pub use check::check_abi;
use check::check_mod_item_types;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::BitSet;
@@ -169,27 +168,24 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
}
}
fn report_forbidden_specialization(
tcx: TyCtxt<'_>,
impl_item: &hir::ImplItemRef,
parent_impl: DefId,
) {
fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) {
let span = tcx.def_span(impl_item);
let ident = tcx.item_name(impl_item);
let mut err = struct_span_err!(
tcx.sess,
impl_item.span,
span,
E0520,
"`{}` specializes an item from a parent `impl`, but \
that item is not marked `default`",
impl_item.ident
"`{}` specializes an item from a parent `impl`, but that item is not marked `default`",
ident,
);
err.span_label(impl_item.span, format!("cannot specialize default item `{}`", impl_item.ident));
err.span_label(span, format!("cannot specialize default item `{}`", ident));
match tcx.span_of_impl(parent_impl) {
Ok(span) => {
err.span_label(span, "parent `impl` is here");
err.note(&format!(
"to specialize, `{}` in the parent `impl` must be marked `default`",
impl_item.ident
ident
));
}
Err(cname) => {

View File

@@ -1716,7 +1716,7 @@ fn receiver_is_valid<'tcx>(
let cause =
ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty).is_ok();
let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty);
// `self: Self` is always valid.
if can_eq_self(receiver_ty) {

View File

@@ -202,8 +202,7 @@ fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'_>, impl_did: LocalDefId)
fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
let span = tcx.hir().span(impl_hir_id);
let span = tcx.def_span(impl_did);
let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));

View File

@@ -14,7 +14,6 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
/// On-demand query: yields a map containing all types mapped to their inherent impls.
pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls {
@@ -57,86 +56,76 @@ const ADD_ATTR: &str =
"alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items";
impl<'tcx> InherentCollect<'tcx> {
fn check_def_id(&mut self, item: &hir::Item<'_>, self_ty: Ty<'tcx>, def_id: DefId, span: Span) {
let impl_def_id = item.owner_id;
if let Some(def_id) = def_id.as_local() {
fn check_def_id(&mut self, impl_def_id: LocalDefId, self_ty: Ty<'tcx>, ty_def_id: DefId) {
if let Some(ty_def_id) = ty_def_id.as_local() {
// Add the implementation to the mapping from implementation to base
// type def ID, if there is a base type for this implementation and
// the implementation does not have any associated traits.
let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
let vec = self.impls_map.inherent_impls.entry(ty_def_id).or_default();
vec.push(impl_def_id.to_def_id());
return;
}
if self.tcx.features().rustc_attrs {
let hir::ItemKind::Impl(&hir::Impl { items, .. }) = item.kind else {
bug!("expected `impl` item: {:?}", item);
};
let items = self.tcx.associated_item_def_ids(impl_def_id);
if !self.tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls) {
if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) {
let impl_span = self.tcx.def_span(impl_def_id);
struct_span_err!(
self.tcx.sess,
span,
impl_span,
E0390,
"cannot define inherent `impl` for a type outside of the crate where the type is defined",
)
.help(INTO_DEFINING_CRATE)
.span_help(span, ADD_ATTR_TO_TY)
.span_help(impl_span, ADD_ATTR_TO_TY)
.emit();
return;
}
for impl_item in items {
if !self
.tcx
.has_attr(impl_item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
{
for &impl_item in items {
if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
let impl_span = self.tcx.def_span(impl_def_id);
struct_span_err!(
self.tcx.sess,
span,
impl_span,
E0390,
"cannot define inherent `impl` for a type outside of the crate where the type is defined",
)
.help(INTO_DEFINING_CRATE)
.span_help(self.tcx.hir().span(impl_item.id.hir_id()), ADD_ATTR)
.span_help(self.tcx.def_span(impl_item), ADD_ATTR)
.emit();
return;
}
}
if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) {
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id.def_id);
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected self type: {:?}", self_ty);
}
} else {
let impl_span = self.tcx.def_span(impl_def_id);
struct_span_err!(
self.tcx.sess,
span,
impl_span,
E0116,
"cannot define inherent `impl` for a type outside of the crate \
where the type is defined"
)
.span_label(span, "impl for type defined outside of crate.")
.span_label(impl_span, "impl for type defined outside of crate.")
.note("define and implement a trait or new type instead")
.emit();
}
}
fn check_primitive_impl(
&mut self,
impl_def_id: LocalDefId,
ty: Ty<'tcx>,
items: &[hir::ImplItemRef],
span: Span,
) {
fn check_primitive_impl(&mut self, impl_def_id: LocalDefId, ty: Ty<'tcx>) {
let items = self.tcx.associated_item_def_ids(impl_def_id);
if !self.tcx.hir().rustc_coherence_is_core() {
if self.tcx.features().rustc_attrs {
for item in items {
if !self
.tcx
.has_attr(item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
{
for &impl_item in items {
if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
let span = self.tcx.def_span(impl_def_id);
struct_span_err!(
self.tcx.sess,
span,
@@ -144,12 +133,13 @@ impl<'tcx> InherentCollect<'tcx> {
"cannot define inherent `impl` for primitive types outside of `core`",
)
.help(INTO_CORE)
.span_help(item.span, ADD_ATTR)
.span_help(self.tcx.def_span(impl_item), ADD_ATTR)
.emit();
return;
}
}
} else {
let span = self.tcx.def_span(impl_def_id);
let mut err = struct_span_err!(
self.tcx.sess,
span,
@@ -177,35 +167,27 @@ impl<'tcx> InherentCollect<'tcx> {
}
fn check_item(&mut self, id: hir::ItemId) {
if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl) {
if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: false }) {
return;
}
let item = self.tcx.hir().item(id);
let impl_span = self.tcx.hir().span(id.hir_id());
let hir::ItemKind::Impl(hir::Impl { of_trait: None, items, .. }) = item.kind else {
return;
};
let self_ty = self.tcx.type_of(item.owner_id);
let id = id.owner_id.def_id;
let item_span = self.tcx.def_span(id);
let self_ty = self.tcx.type_of(id);
match *self_ty.kind() {
ty::Adt(def, _) => {
self.check_def_id(item, self_ty, def.did(), impl_span);
}
ty::Foreign(did) => {
self.check_def_id(item, self_ty, did, impl_span);
}
ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
ty::Foreign(did) => self.check_def_id(id, self_ty, did),
ty::Dynamic(data, ..) if data.principal_def_id().is_some() => {
self.check_def_id(item, self_ty, data.principal_def_id().unwrap(), impl_span);
self.check_def_id(id, self_ty, data.principal_def_id().unwrap());
}
ty::Dynamic(..) => {
struct_span_err!(
self.tcx.sess,
impl_span,
item_span,
E0785,
"cannot define inherent `impl` for a dyn auto trait"
)
.span_label(impl_span, "impl requires at least one non-auto trait")
.span_label(item_span, "impl requires at least one non-auto trait")
.note("define and implement a new trait or type instead")
.emit();
}
@@ -221,18 +203,16 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Ref(..)
| ty::Never
| ty::FnPtr(_)
| ty::Tuple(..) => {
self.check_primitive_impl(item.owner_id.def_id, self_ty, items, impl_span)
}
| ty::Tuple(..) => self.check_primitive_impl(id, self_ty),
ty::Alias(..) | ty::Param(_) => {
let mut err = struct_span_err!(
self.tcx.sess,
impl_span,
item_span,
E0118,
"no nominal type found for inherent implementation"
);
err.span_label(impl_span, "impl requires a nominal type")
err.span_label(item_span, "impl requires a nominal type")
.note("either implement a trait on it or create a newtype to wrap it instead");
err.emit();
@@ -245,7 +225,7 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => {
bug!("unexpected impl self type of impl: {:?} {:?}", item.owner_id, self_ty);
bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty);
}
ty::Error(_) => {}
}

View File

@@ -39,16 +39,17 @@ fn do_orphan_check_impl<'tcx>(
) -> Result<(), ErrorGuaranteed> {
let trait_def_id = trait_ref.def_id;
match traits::orphan_check(tcx, def_id.to_def_id()) {
Ok(()) => {}
Err(err) => {
let item = tcx.hir().expect_item(def_id);
let hir::ItemKind::Impl(impl_) = item.kind else {
bug!("{:?} is not an impl: {:?}", def_id, item);
};
let sp = tcx.def_span(def_id);
let tr = impl_.of_trait.as_ref().unwrap();
let sp = tcx.def_span(def_id);
match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
Ok(()) => {}
Err(err) => emit_orphan_check_error(
emit_orphan_check_error(
tcx,
sp,
item.span,
@@ -57,7 +58,8 @@ fn do_orphan_check_impl<'tcx>(
impl_.self_ty.span,
&impl_.generics,
err,
)?,
)?
}
}
// In addition to the above rules, we restrict impls of auto traits
@@ -235,7 +237,10 @@ fn do_orphan_check_impl<'tcx>(
| ty::GeneratorWitnessMIR(..)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Infer(..) => span_bug!(sp, "weird self type for autotrait impl"),
| ty::Infer(..) => {
let sp = tcx.def_span(def_id);
span_bug!(sp, "weird self type for autotrait impl")
}
ty::Error(..) => (LocalImpl::Allow, NonlocalImpl::Allow),
};
@@ -254,6 +259,7 @@ fn do_orphan_check_impl<'tcx>(
is one of the trait object's trait bounds",
trait = tcx.def_path_str(trait_def_id),
);
let sp = tcx.def_span(def_id);
let reported =
struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit();
return Err(reported);
@@ -282,6 +288,7 @@ fn do_orphan_check_impl<'tcx>(
non-struct/enum type",
)),
} {
let sp = tcx.def_span(def_id);
let reported =
struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
return Err(reported);

View File

@@ -1563,7 +1563,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// See issue #83753. If someone writes an associated type on a non-trait, just treat it as
// there being no supertrait HRTBs.
match tcx.def_kind(def_id) {
DefKind::Trait | DefKind::TraitAlias | DefKind::Impl => {}
DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
_ => break None,
}

View File

@@ -55,7 +55,7 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
let min_specialization = tcx.features().min_specialization;
let module = tcx.hir_module_items(module_def_id);
for id in module.items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
enforce_impl_params_are_constrained(tcx, id.owner_id.def_id);
if min_specialization {
check_min_specialization(tcx, id.owner_id.def_id);

View File

@@ -298,6 +298,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// call's arguments and we can provide a more explicit span.
let sig = self.tcx.fn_sig(def_id).subst_identity();
let def_self_ty = sig.input(0).skip_binder();
let param_tys = sig.inputs().skip_binder().iter().skip(1);
// If there's an arity mismatch, pointing out the call as the source of an inference
// can be misleading, so we skip it.
if param_tys.len() != args.len() {
continue;
}
let rcvr_ty = self.node_ty(rcvr.hir_id);
// Get the evaluated type *after* calling the method call, so that the influence
// of the arguments can be reflected in the receiver type. The receiver
@@ -321,15 +327,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut param_args = FxHashMap::default();
let mut param_expected = FxHashMap::default();
let mut param_found = FxHashMap::default();
if self.can_eq(self.param_env, ty, found).is_ok() {
if self.can_eq(self.param_env, ty, found) {
// We only point at the first place where the found type was inferred.
for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() {
for (param_ty, arg) in param_tys.zip(args) {
if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() {
// We found an argument that references a type parameter in `Self`,
// so we assume that this is the argument that caused the found
// type, which we know already because of `can_eq` above was first
// inferred in this method call.
let arg = &args[i];
let arg_ty = self.node_ty(arg.hir_id);
if !arg.span.overlaps(mismatch_span) {
err.span_label(
@@ -369,7 +374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for (param, (arg, arg_ty)) in param_args.iter() {
let Some(expected) = param_expected.get(param) else { continue; };
let Some(found) = param_found.get(param) else { continue; };
if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; }
if !self.can_eq(self.param_env, *arg_ty, *found) { continue; }
self.emit_coerce_suggestions(err, arg, *found, *expected, None, None);
}
@@ -379,7 +384,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
if ty != prev
&& param_args.is_empty()
&& self.can_eq(self.param_env, ty, found).is_ok()
&& self.can_eq(self.param_env, ty, found)
{
// We only point at the first place where the found type was inferred.
if !segment.ident.span.overlaps(mismatch_span) {
@@ -401,7 +406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
if ty != prev
&& let Some(span) = prev_span
&& self.can_eq(self.param_env, ty, found).is_ok()
&& self.can_eq(self.param_env, ty, found)
{
// We only point at the first place where the found type was inferred.
// We use the *previous* span because if the type is known *here* it means
@@ -764,7 +769,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::Adt(expected_adt, substs) = expected.kind() {
if let hir::ExprKind::Field(base, ident) = expr.kind {
let base_ty = self.typeck_results.borrow().expr_ty(base);
if self.can_eq(self.param_env, base_ty, expected).is_ok()
if self.can_eq(self.param_env, base_ty, expected)
&& let Some(base_span) = base.span.find_ancestor_inside(expr.span)
{
err.span_suggestion_verbose(
@@ -1357,7 +1362,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr),
_,
&ty::Ref(_, checked, _),
) if self.can_sub(self.param_env, checked, expected).is_ok() => {
) if self.can_sub(self.param_env, checked, expected) => {
// We have `&T`, check if what was expected was `T`. If so,
// we may want to suggest removing a `&`.
if sm.is_imported(expr.span) {
@@ -2003,7 +2008,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; };
if self.can_eq(self.param_env, expected_ty, ty).is_ok() {
if self.can_eq(self.param_env, expected_ty, ty) {
err.span_suggestion_short(
stmt.span.with_lo(tail_expr.span.hi()),
"remove this semicolon",

View File

@@ -1015,7 +1015,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let expr_inner_ty = substs.type_at(0);
let expected_inner_ty = expected_substs.type_at(0);
if let ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
&& self.can_eq(self.param_env, *ty, expected_inner_ty).is_ok()
&& self.can_eq(self.param_env, *ty, expected_inner_ty)
{
let def_path = self.tcx.def_path_str(adt_def.did());
if self.type_is_copy_modulo_regions(self.param_env, *ty, expr.span) {
@@ -1054,7 +1054,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(result_did) = self.tcx.get_diagnostic_item(sym::Result)
&& adt_def.did() == result_did
// Check that the error types are equal
&& self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1)).is_ok()
&& self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1))
{
return suggest_copied_or_cloned();
} else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)

View File

@@ -517,8 +517,7 @@ fn method_autoderef_steps<'tcx>(
.by_ref()
.map(|(ty, d)| {
let step = CandidateStep {
self_ty: infcx
.make_query_response_ignoring_pending_obligations(inference_vars.clone(), ty),
self_ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, ty),
autoderefs: d,
from_unsafe_deref: reached_raw_pointer,
unsize: false,
@@ -936,7 +935,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
return false;
}
}
self.can_sub(self.param_env, fty.output(), expected).is_ok()
self.can_sub(self.param_env, fty.output(), expected)
}),
_ => false,
}

View File

@@ -90,7 +90,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
if let Some(expr) = ti.origin_expr {
self.suggest_fn_call(&mut diag, expr, expected, |output| {
self.can_eq(self.param_env, output, actual).is_ok()
self.can_eq(self.param_env, output, actual)
});
}
Some(diag)
@@ -675,7 +675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
match (expected.kind(), actual.kind(), ba) {
(ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::NONE)
if self.can_eq(self.param_env, *inner_ty, actual).is_ok() =>
if self.can_eq(self.param_env, *inner_ty, actual) =>
{
err.span_suggestion_verbose(
span.shrink_to_lo(),
@@ -685,7 +685,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
(_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::REF)
if self.can_eq(self.param_env, expected, *inner_ty).is_ok() =>
if self.can_eq(self.param_env, expected, *inner_ty) =>
{
err.span_suggestion_verbose(
span.with_hi(span.lo() + BytePos(4)),

View File

@@ -933,3 +933,216 @@ pub struct ButNeedsToSatisfy {
pub has_lifetime: bool,
pub lifetime: String,
}
#[derive(Diagnostic)]
#[diag(infer_outlives_content, code = "E0312")]
pub struct OutlivesContent<'a> {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Diagnostic)]
#[diag(infer_outlives_bound, code = "E0476")]
pub struct OutlivesBound<'a> {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Diagnostic)]
#[diag(infer_fullfill_req_lifetime, code = "E0477")]
pub struct FullfillReqLifetime<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
#[subdiagnostic]
pub note: Option<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Diagnostic)]
#[diag(infer_lf_bound_not_satisfied, code = "E0478")]
pub struct LfBoundNotSatisfied<'a> {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Diagnostic)]
#[diag(infer_ref_longer_than_data, code = "E0491")]
pub struct RefLongerThanData<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
#[subdiagnostic]
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Subdiagnostic)]
pub enum WhereClauseSuggestions {
#[suggestion(
infer_where_remove,
code = "",
applicability = "machine-applicable",
style = "verbose"
)]
Remove {
#[primary_span]
span: Span,
},
#[suggestion(
infer_where_copy_predicates,
code = "{space}where {trait_predicates}",
applicability = "machine-applicable",
style = "verbose"
)]
CopyPredicates {
#[primary_span]
span: Span,
space: &'static str,
trait_predicates: String,
},
}
#[derive(Subdiagnostic)]
pub enum SuggestRemoveSemiOrReturnBinding {
#[multipart_suggestion(infer_srs_remove_and_box, applicability = "machine-applicable")]
RemoveAndBox {
#[suggestion_part(code = "Box::new(")]
first_lo: Span,
#[suggestion_part(code = ")")]
first_hi: Span,
#[suggestion_part(code = "Box::new(")]
second_lo: Span,
#[suggestion_part(code = ")")]
second_hi: Span,
#[suggestion_part(code = "")]
sp: Span,
},
#[suggestion(
infer_srs_remove,
style = "short",
code = "",
applicability = "machine-applicable"
)]
Remove {
#[primary_span]
sp: Span,
},
#[suggestion(
infer_srs_add,
style = "verbose",
code = "{code}",
applicability = "maybe-incorrect"
)]
Add {
#[primary_span]
sp: Span,
code: String,
ident: Ident,
},
#[note(infer_srs_add_one)]
AddOne {
#[primary_span]
spans: MultiSpan,
},
}
#[derive(Subdiagnostic)]
pub enum ConsiderAddingAwait {
#[help(infer_await_both_futures)]
BothFuturesHelp,
#[multipart_suggestion(infer_await_both_futures, applicability = "maybe-incorrect")]
BothFuturesSugg {
#[suggestion_part(code = ".await")]
first: Span,
#[suggestion_part(code = ".await")]
second: Span,
},
#[suggestion(
infer_await_future,
code = ".await",
style = "verbose",
applicability = "maybe-incorrect"
)]
FutureSugg {
#[primary_span]
span: Span,
},
#[note(infer_await_note)]
FutureSuggNote {
#[primary_span]
span: Span,
},
#[multipart_suggestion(
infer_await_future,
style = "verbose",
applicability = "maybe-incorrect"
)]
FutureSuggMultiple {
#[suggestion_part(code = ".await")]
spans: Vec<Span>,
},
}
#[derive(Diagnostic)]
pub enum PlaceholderRelationLfNotSatisfied {
#[diag(infer_lf_bound_not_satisfied)]
HasBoth {
#[primary_span]
span: Span,
#[note(infer_prlf_defined_with_sub)]
sub_span: Span,
#[note(infer_prlf_must_oultive_with_sup)]
sup_span: Span,
sub_symbol: Symbol,
sup_symbol: Symbol,
#[note(infer_prlf_known_limitation)]
note: (),
},
#[diag(infer_lf_bound_not_satisfied)]
HasSub {
#[primary_span]
span: Span,
#[note(infer_prlf_defined_with_sub)]
sub_span: Span,
#[note(infer_prlf_must_oultive_without_sup)]
sup_span: Span,
sub_symbol: Symbol,
#[note(infer_prlf_known_limitation)]
note: (),
},
#[diag(infer_lf_bound_not_satisfied)]
HasSup {
#[primary_span]
span: Span,
#[note(infer_prlf_defined_without_sub)]
sub_span: Span,
#[note(infer_prlf_must_oultive_with_sup)]
sup_span: Span,
sup_symbol: Symbol,
#[note(infer_prlf_known_limitation)]
note: (),
},
#[diag(infer_lf_bound_not_satisfied)]
HasNone {
#[primary_span]
span: Span,
#[note(infer_prlf_defined_without_sub)]
sub_span: Span,
#[note(infer_prlf_must_oultive_without_sup)]
sup_span: Span,
#[note(infer_prlf_known_limitation)]
note: (),
},
#[diag(infer_lf_bound_not_satisfied)]
OnlyPrimarySpan {
#[primary_span]
span: Span,
#[note(infer_prlf_known_limitation)]
note: (),
},
}

View File

@@ -121,16 +121,42 @@ impl<'a> DescriptionCtx<'a> {
pub enum PrefixKind {
Empty,
RefValidFor,
ContentValidFor,
TypeObjValidFor,
SourcePointerValidFor,
TypeSatisfy,
TypeOutlive,
LfParamInstantiatedWith,
LfParamMustOutlive,
LfInstantiatedWith,
LfMustOutlive,
PointerValidFor,
DataValidFor,
}
pub enum SuffixKind {
Empty,
Continues,
ReqByBinding,
}
impl IntoDiagnosticArg for PrefixKind {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
let kind = match self {
Self::Empty => "empty",
Self::RefValidFor => "ref_valid_for",
Self::ContentValidFor => "content_valid_for",
Self::TypeObjValidFor => "type_obj_valid_for",
Self::SourcePointerValidFor => "source_pointer_valid_for",
Self::TypeSatisfy => "type_satisfy",
Self::TypeOutlive => "type_outlive",
Self::LfParamInstantiatedWith => "lf_param_instantiated_with",
Self::LfParamMustOutlive => "lf_param_must_outlive",
Self::LfInstantiatedWith => "lf_instantiated_with",
Self::LfMustOutlive => "lf_must_outlive",
Self::PointerValidFor => "pointer_valid_for",
Self::DataValidFor => "data_valid_for",
}
.into();
rustc_errors::DiagnosticArgValue::Str(kind)
@@ -140,7 +166,9 @@ impl IntoDiagnosticArg for PrefixKind {
impl IntoDiagnosticArg for SuffixKind {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
let kind = match self {
Self::Empty => "empty",
Self::Continues => "continues",
Self::ReqByBinding => "req_by_binding",
}
.into();
rustc_errors::DiagnosticArgValue::Str(kind)
@@ -166,17 +194,19 @@ impl RegionExplanation<'_> {
}
impl AddToDiagnostic for RegionExplanation<'_> {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
if let Some(span) = self.desc.span {
diag.span_note(span, fluent::infer_region_explanation);
} else {
diag.note(fluent::infer_region_explanation);
}
self.desc.add_to(diag);
diag.set_arg("pref_kind", self.prefix);
diag.set_arg("suff_kind", self.suffix);
let desc_span = self.desc.span;
self.desc.add_to(diag);
let msg = f(diag, fluent::infer_region_explanation.into());
if let Some(span) = desc_span {
diag.span_note(span, msg);
} else {
diag.note(msg);
}
}
}

View File

@@ -751,15 +751,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
};
let msg = "`match` arms have incompatible types";
err.span_label(outer, msg);
self.suggest_remove_semi_or_return_binding(
err,
if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
prior_arm_block_id,
prior_arm_ty,
prior_arm_span,
arm_block_id,
arm_ty,
arm_span,
);
) {
err.subdiagnostic(subdiag);
}
if let Some(ret_sp) = opt_suggest_box_span {
// Get return type span and point to it.
self.suggest_boxing_for_return_impl_trait(
@@ -784,15 +785,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let Some(sp) = outer_span {
err.span_label(sp, "`if` and `else` have incompatible types");
}
self.suggest_remove_semi_or_return_binding(
err,
if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
Some(then_id),
then_ty,
then_span,
Some(else_id),
else_ty,
else_span,
);
) {
err.subdiagnostic(subdiag);
}
if let Some(ret_sp) = opt_suggest_box_span {
self.suggest_boxing_for_return_impl_trait(
err,

View File

@@ -1061,7 +1061,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
};
let parent_def_id = generics.parent.unwrap();
if tcx.def_kind(parent_def_id) == DefKind::Impl {
if let DefKind::Impl { .. } = tcx.def_kind(parent_def_id) {
let parent_ty = tcx.bound_type_of(parent_def_id).subst(tcx, substs);
match (parent_ty.kind(), &ty.kind) {
(

View File

@@ -1,5 +1,8 @@
use crate::infer::{
use crate::{
errors::PlaceholderRelationLfNotSatisfied,
infer::{
error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin,
},
};
use rustc_data_structures::intern::Interned;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
@@ -16,8 +19,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)),
Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)),
)) => {
let msg = "lifetime bound not satisfied";
let mut err = self.tcx().sess.struct_span_err(*span, msg);
let span = *span;
let (sub_span, sub_symbol) = match sub_name {
ty::BrNamed(def_id, symbol) => {
(Some(self.tcx().def_span(def_id)), Some(symbol))
@@ -32,41 +34,47 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
ty::BrAnon(_, span) => (*span, None),
ty::BrEnv => (None, None),
};
match (sub_span, sup_span, sub_symbol, sup_symbol) {
(Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => {
err.span_note(
let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) {
(Some(sub_span), Some(sup_span), Some(&sub_symbol), Some(&sup_symbol)) => {
PlaceholderRelationLfNotSatisfied::HasBoth {
span,
sub_span,
format!("the lifetime `{sub_symbol}` defined here..."),
);
err.span_note(
sup_span,
format!("...must outlive the lifetime `{sup_symbol}` defined here"),
);
sub_symbol,
sup_symbol,
note: (),
}
(Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => {
err.span_note(sub_span, "the lifetime defined here...");
err.span_note(
sup_span,
format!("...must outlive the lifetime `{sup_symbol}` defined here"),
);
}
(Some(sub_span), Some(sup_span), Some(sub_symbol), _) => {
err.span_note(
(Some(sub_span), Some(sup_span), _, Some(&sup_symbol)) => {
PlaceholderRelationLfNotSatisfied::HasSup {
span,
sub_span,
format!("the lifetime `{sub_symbol}` defined here..."),
);
err.span_note(sup_span, "...must outlive the lifetime defined here");
sup_span,
sup_symbol,
note: (),
}
}
(Some(sub_span), Some(sup_span), Some(&sub_symbol), _) => {
PlaceholderRelationLfNotSatisfied::HasSub {
span,
sub_span,
sup_span,
sub_symbol,
note: (),
}
}
(Some(sub_span), Some(sup_span), _, _) => {
err.span_note(sub_span, "the lifetime defined here...");
err.span_note(sup_span, "...must outlive the lifetime defined here");
PlaceholderRelationLfNotSatisfied::HasNone {
span,
sub_span,
sup_span,
note: (),
}
_ => {}
}
err.note("this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)");
Some(err)
_ => PlaceholderRelationLfNotSatisfied::OnlyPrimarySpan { span, note: () },
};
Some(self.tcx().sess.create_err(diag))
}
_ => None,
}
}

View File

@@ -1,9 +1,11 @@
use crate::errors::RegionOriginNote;
use crate::errors::{
note_and_explain, FullfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
};
use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
use crate::infer::{self, SubregionOrigin};
use rustc_errors::{
fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
ErrorGuaranteed,
fluent, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::traits::ObligationCauseCode;
@@ -119,130 +121,105 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err
}
infer::Reborrow(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0312,
"lifetime of reference outlives lifetime of borrowed content..."
);
note_and_explain_region(
let reference_valid = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"...the reference is valid for ",
sub,
"...",
None,
note_and_explain::PrefixKind::RefValidFor,
note_and_explain::SuffixKind::Continues,
);
note_and_explain_region(
let content_valid = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"...but the borrowed content is only valid for ",
sup,
"",
None,
note_and_explain::PrefixKind::ContentValidFor,
note_and_explain::SuffixKind::Empty,
);
err
OutlivesContent {
span,
notes: reference_valid.into_iter().chain(content_valid).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::RelateObjectBound(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0476,
"lifetime of the source pointer does not outlive lifetime bound of the \
object type"
);
note_and_explain_region(
let object_valid = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"object type is valid for ",
sub,
"",
None,
note_and_explain::PrefixKind::TypeObjValidFor,
note_and_explain::SuffixKind::Empty,
);
note_and_explain_region(
let pointer_valid = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"source pointer is only valid for ",
sup,
"",
None,
note_and_explain::PrefixKind::SourcePointerValidFor,
note_and_explain::SuffixKind::Empty,
);
err
OutlivesBound {
span,
notes: object_valid.into_iter().chain(pointer_valid).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::RelateParamBound(span, ty, opt_span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0477,
"the type `{}` does not fulfill the required lifetime",
self.ty_to_string(ty)
let prefix = match *sub {
ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
_ => note_and_explain::PrefixKind::TypeOutlive,
};
let suffix = if opt_span.is_some() {
note_and_explain::SuffixKind::ReqByBinding
} else {
note_and_explain::SuffixKind::Empty
};
let note = note_and_explain::RegionExplanation::new(
self.tcx, sub, opt_span, prefix, suffix,
);
match *sub {
ty::ReStatic => note_and_explain_region(
self.tcx,
&mut err,
"type must satisfy ",
sub,
if opt_span.is_some() { " as required by this binding" } else { "" },
opt_span,
),
_ => note_and_explain_region(
self.tcx,
&mut err,
"type must outlive ",
sub,
if opt_span.is_some() { " as required by this binding" } else { "" },
opt_span,
),
}
err
FullfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note }
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::RelateRegionParamBound(span) => {
let mut err =
struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
note_and_explain_region(
let param_instantiated = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"lifetime parameter instantiated with ",
sup,
"",
None,
note_and_explain::PrefixKind::LfParamInstantiatedWith,
note_and_explain::SuffixKind::Empty,
);
note_and_explain_region(
let param_must_outlive = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"but lifetime parameter must outlive ",
sub,
"",
None,
note_and_explain::PrefixKind::LfParamMustOutlive,
note_and_explain::SuffixKind::Empty,
);
err
LfBoundNotSatisfied {
span,
notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::ReferenceOutlivesReferent(ty, span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0491,
"in type `{}`, reference has a longer lifetime than the data it references",
self.ty_to_string(ty)
);
note_and_explain_region(
let pointer_valid = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"the pointer is valid for ",
sub,
"",
None,
note_and_explain::PrefixKind::PointerValidFor,
note_and_explain::SuffixKind::Empty,
);
note_and_explain_region(
let data_valid = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"but the referenced data is only valid for ",
sup,
"",
None,
note_and_explain::PrefixKind::DataValidFor,
note_and_explain::SuffixKind::Empty,
);
err
RefLongerThanData {
span,
ty: self.resolve_vars_if_possible(ty),
notes: pointer_valid.into_iter().chain(data_valid).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
let mut err = self.report_extra_impl_obligation(
@@ -279,25 +256,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err
}
infer::AscribeUserTypeProvePredicate(span) => {
let mut err =
struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
note_and_explain_region(
let instantiated = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"lifetime instantiated with ",
sup,
"",
None,
note_and_explain::PrefixKind::LfInstantiatedWith,
note_and_explain::SuffixKind::Empty,
);
note_and_explain_region(
let must_outlive = note_and_explain::RegionExplanation::new(
self.tcx,
&mut err,
"but lifetime must outlive ",
sub,
"",
None,
note_and_explain::PrefixKind::LfMustOutlive,
note_and_explain::SuffixKind::Empty,
);
err
LfBoundNotSatisfied {
span,
notes: instantiated.into_iter().chain(must_outlive).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
};
if sub.is_error() || sup.is_error() {
@@ -347,22 +324,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; };
if trait_predicates.is_empty() {
err.span_suggestion_verbose(
generics.where_clause_span,
"remove the `where` clause",
String::new(),
Applicability::MachineApplicable,
);
let suggestion = if trait_predicates.is_empty() {
WhereClauseSuggestions::Remove { span: generics.where_clause_span }
} else {
let space = if generics.where_clause_span.is_empty() { " " } else { "" };
err.span_suggestion_verbose(
generics.where_clause_span,
"copy the `where` clause predicates from the trait",
format!("{space}where {}", trait_predicates.join(", ")),
Applicability::MachineApplicable,
);
WhereClauseSuggestions::CopyPredicates {
span: generics.where_clause_span,
space,
trait_predicates: trait_predicates.join(", "),
}
};
err.subdiagnostic(suggestion);
}
pub(super) fn report_placeholder_failure(

View File

@@ -504,7 +504,9 @@ fn foo(&self) -> Self::T { String::new() }
let methods: Vec<(Span, String)> = items
.in_definition_order()
.filter(|item| {
ty::AssocKind::Fn == item.kind && Some(item.name) != current_method_ident
ty::AssocKind::Fn == item.kind
&& Some(item.name) != current_method_ident
&& !tcx.is_doc_hidden(item.def_id)
})
.filter_map(|item| {
let method = tcx.fn_sig(item.def_id).subst_identity();
@@ -576,7 +578,7 @@ fn foo(&self) -> Self::T { String::new() }
tcx.impl_defaultness(item.id.owner_id)
{
let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity();
if self.infcx.can_eq(param_env, assoc_ty, found).is_ok() {
if self.infcx.can_eq(param_env, assoc_ty, found) {
diag.span_label(
item.span,
"associated type defaults can't be assumed inside the \
@@ -598,7 +600,7 @@ fn foo(&self) -> Self::T { String::new() }
if let hir::AssocItemKind::Type = item.kind {
let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity();
if self.infcx.can_eq(param_env, assoc_ty, found).is_ok() {
if self.infcx.can_eq(param_env, assoc_ty, found) {
diag.span_label(item.span, "expected this associated type");
return true;
}

View File

@@ -11,21 +11,22 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitable};
use rustc_span::{sym, BytePos, Span};
use crate::errors::SuggAddLetForLetChains;
use crate::errors::{
ConsiderAddingAwait, SuggAddLetForLetChains, SuggestRemoveSemiOrReturnBinding,
};
use super::TypeErrCtxt;
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pub(super) fn suggest_remove_semi_or_return_binding(
&self,
err: &mut Diagnostic,
first_id: Option<hir::HirId>,
first_ty: Ty<'tcx>,
first_span: Span,
second_id: Option<hir::HirId>,
second_ty: Ty<'tcx>,
second_span: Span,
) {
) -> Option<SuggestRemoveSemiOrReturnBinding> {
let remove_semicolon = [
(first_id, self.resolve_vars_if_possible(second_ty)),
(second_id, self.resolve_vars_if_possible(first_ty)),
@@ -37,35 +38,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
});
match remove_semicolon {
Some((sp, StatementAsExpression::NeedsBoxing)) => {
err.multipart_suggestion(
"consider removing this semicolon and boxing the expressions",
vec![
(first_span.shrink_to_lo(), "Box::new(".to_string()),
(first_span.shrink_to_hi(), ")".to_string()),
(second_span.shrink_to_lo(), "Box::new(".to_string()),
(second_span.shrink_to_hi(), ")".to_string()),
(sp, String::new()),
],
Applicability::MachineApplicable,
);
Some(SuggestRemoveSemiOrReturnBinding::RemoveAndBox {
first_lo: first_span.shrink_to_lo(),
first_hi: first_span.shrink_to_hi(),
second_lo: second_span.shrink_to_lo(),
second_hi: second_span.shrink_to_hi(),
sp,
})
}
Some((sp, StatementAsExpression::CorrectType)) => {
err.span_suggestion_short(
sp,
"consider removing this semicolon",
"",
Applicability::MachineApplicable,
);
Some(SuggestRemoveSemiOrReturnBinding::Remove { sp })
}
None => {
let mut ret = None;
for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
if let Some(id) = id
&& let hir::Node::Block(blk) = self.tcx.hir().get(id)
&& self.consider_returning_binding(blk, ty, err)
&& let Some(diag) = self.consider_returning_binding_diag(blk, ty)
{
ret = Some(diag);
break;
}
}
ret
}
}
}
@@ -198,7 +193,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
return;
}
match (
let subdiag = match (
self.get_impl_future_output_ty(exp_found.expected),
self.get_impl_future_output_ty(exp_found.found),
) {
@@ -207,65 +202,56 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
{
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id);
diag.multipart_suggestion(
"consider `await`ing on both `Future`s",
vec![
(then_span.shrink_to_hi(), ".await".to_string()),
(exp_span.shrink_to_hi(), ".await".to_string()),
],
Applicability::MaybeIncorrect,
);
Some(ConsiderAddingAwait::BothFuturesSugg {
first: then_span.shrink_to_hi(),
second: exp_span.shrink_to_hi(),
})
}
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
prior_arms,
..
}) => {
if let [.., arm_span] = &prior_arms[..] {
diag.multipart_suggestion(
"consider `await`ing on both `Future`s",
vec![
(arm_span.shrink_to_hi(), ".await".to_string()),
(exp_span.shrink_to_hi(), ".await".to_string()),
],
Applicability::MaybeIncorrect,
);
Some(ConsiderAddingAwait::BothFuturesSugg {
first: arm_span.shrink_to_hi(),
second: exp_span.shrink_to_hi(),
})
} else {
diag.help("consider `await`ing on both `Future`s");
Some(ConsiderAddingAwait::BothFuturesHelp)
}
}
_ => {
diag.help("consider `await`ing on both `Future`s");
}
_ => Some(ConsiderAddingAwait::BothFuturesHelp),
},
(_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
self.suggest_await_on_future(diag, exp_span);
diag.span_note(exp_span, "calling an async function returns a future");
// FIXME: Seems like we can't have a suggestion and a note with different spans in a single subdiagnostic
diag.subdiagnostic(ConsiderAddingAwait::FutureSugg {
span: exp_span.shrink_to_hi(),
});
Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span })
}
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
{
ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
self.suggest_await_on_future(diag, then_span.shrink_to_hi());
Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
}
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id);
self.suggest_await_on_future(diag, then_span.shrink_to_hi());
Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
}
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
ref prior_arms,
..
}) => {
diag.multipart_suggestion_verbose(
"consider `await`ing on the `Future`",
prior_arms
.iter()
.map(|arm| (arm.shrink_to_hi(), ".await".to_string()))
.collect(),
Applicability::MaybeIncorrect,
);
}) => Some({
ConsiderAddingAwait::FutureSuggMultiple {
spans: prior_arms.iter().map(|arm| arm.shrink_to_hi()).collect(),
}
_ => {}
}),
_ => None,
},
_ => {}
_ => None,
};
if let Some(subdiag) = subdiag {
diag.subdiagnostic(subdiag);
}
}
@@ -655,16 +641,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
/// Suggest returning a local binding with a compatible type if the block
/// has no return expression.
pub fn consider_returning_binding(
pub fn consider_returning_binding_diag(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
err: &mut Diagnostic,
) -> bool {
) -> Option<SuggestRemoveSemiOrReturnBinding> {
let blk = blk.innermost_block();
// Do not suggest if we have a tail expr.
if blk.expr.is_some() {
return false;
return None;
}
let mut shadowed = FxIndexSet::default();
let mut candidate_idents = vec![];
@@ -733,7 +718,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
match &candidate_idents[..] {
[(ident, _ty)] => {
let sm = self.tcx.sess.source_map();
if let Some(stmt) = blk.stmts.last() {
let (span, sugg) = if let Some(stmt) = blk.stmts.last() {
let stmt_span = sm.stmt_span(stmt.span, blk.span);
let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(stmt_span)
@@ -742,12 +727,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} else {
format!(" {ident}")
};
err.span_suggestion_verbose(
stmt_span.shrink_to_hi(),
format!("consider returning the local binding `{ident}`"),
sugg,
Applicability::MaybeIncorrect,
);
(stmt_span.shrink_to_hi(), sugg)
} else {
let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
@@ -757,21 +737,34 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
format!(" {ident} ")
};
let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
err.span_suggestion_verbose(
(
sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
format!("consider returning the local binding `{ident}`"),
sugg,
Applicability::MaybeIncorrect,
);
}
true
)
};
Some(SuggestRemoveSemiOrReturnBinding::Add { sp: span, code: sugg, ident: *ident })
}
values if (1..3).contains(&values.len()) => {
let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
err.span_note(spans, "consider returning one of these bindings");
Some(SuggestRemoveSemiOrReturnBinding::AddOne { spans: spans.into() })
}
_ => None,
}
}
pub fn consider_returning_binding(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
err: &mut Diagnostic,
) -> bool {
let diag = self.consider_returning_binding_diag(blk, expected_ty);
match diag {
Some(diag) => {
err.subdiagnostic(diag);
true
}
_ => false,
None => false,
}
}
}

View File

@@ -880,30 +880,20 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
}
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
self.probe(|_| {
self.at(origin, param_env).sub(a, b).map(|InferOk { obligations: _, .. }| {
// Ignore obligations, since we are unrolling
// everything anyway.
})
})
self.probe(|_| self.at(origin, param_env).sub(a, b).is_ok())
}
pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
self.probe(|_| {
self.at(origin, param_env).eq(a, b).map(|InferOk { obligations: _, .. }| {
// Ignore obligations, since we are unrolling
// everything anyway.
})
})
self.probe(|_| self.at(origin, param_env).eq(a, b).is_ok())
}
#[instrument(skip(self), level = "debug")]

View File

@@ -691,7 +691,6 @@ fn test_unstable_options_tracking_hash() {
untracked!(proc_macro_execution_strategy, ProcMacroExecutionStrategy::CrossThread);
untracked!(profile_closures, true);
untracked!(query_dep_graph, true);
untracked!(save_analysis, true);
untracked!(self_profile, SwitchWithOptPath::Enabled(None));
untracked!(self_profile_events, Some(vec![String::new()]));
untracked!(span_debug, true);

View File

@@ -838,7 +838,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
| DefKind::ForeignMod
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::Field => true,
DefKind::TyParam
| DefKind::ConstParam
@@ -873,7 +873,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
| DefKind::ImplTraitPlaceholder
| DefKind::Enum
| DefKind::Union
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::Trait
| DefKind::TraitAlias
| DefKind::Macro(..)
@@ -951,7 +951,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
| DefKind::Const
| DefKind::ForeignMod
| DefKind::TyAlias
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::Trait
| DefKind::TraitAlias
| DefKind::Macro(..)
@@ -988,7 +988,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::Field
| DefKind::TyParam
| DefKind::Closure
@@ -1018,7 +1018,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
| DefKind::TyAlias
| DefKind::OpaqueTy
| DefKind::ForeignTy
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::AssocFn
| DefKind::AssocConst
| DefKind::Closure
@@ -1081,7 +1081,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::ForeignTy
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::AssocFn
| DefKind::Closure
| DefKind::Generator
@@ -1860,7 +1860,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
FxHashMap::default();
for id in tcx.hir().items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) {
let trait_ref = trait_ref.subst_identity();
@@ -2261,7 +2261,7 @@ pub fn provide(providers: &mut Providers) {
let mut trait_impls = Vec::new();
for id in tcx.hir().items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl)
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
&& tcx.impl_trait_ref(id.owner_id).is_some()
{
trait_impls.push(id.owner_id.to_def_id())

View File

@@ -136,7 +136,8 @@ fixed_size_enum! {
( Field )
( LifetimeParam )
( GlobalAsm )
( Impl )
( Impl { of_trait: false } )
( Impl { of_trait: true } )
( Closure )
( Generator )
( Static(ast::Mutability::Not) )

View File

@@ -203,7 +203,7 @@ impl<'hir> Map<'hir> {
ItemKind::Use(..) => DefKind::Use,
ItemKind::ForeignMod { .. } => DefKind::ForeignMod,
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
ItemKind::Impl { .. } => DefKind::Impl,
ItemKind::Impl(impl_) => DefKind::Impl { of_trait: impl_.of_trait.is_some() },
},
Node::ForeignItem(item) => match item.kind {
ForeignItemKind::Fn(..) => DefKind::Fn,

View File

@@ -19,29 +19,29 @@ pub trait PointerArithmetic: HasDataLayout {
#[inline(always)]
fn max_size_of_val(&self) -> Size {
Size::from_bytes(self.machine_isize_max())
Size::from_bytes(self.target_isize_max())
}
#[inline]
fn machine_usize_max(&self) -> u64 {
fn target_usize_max(&self) -> u64 {
self.pointer_size().unsigned_int_max().try_into().unwrap()
}
#[inline]
fn machine_isize_min(&self) -> i64 {
fn target_isize_min(&self) -> i64 {
self.pointer_size().signed_int_min().try_into().unwrap()
}
#[inline]
fn machine_isize_max(&self) -> i64 {
fn target_isize_max(&self) -> i64 {
self.pointer_size().signed_int_max().try_into().unwrap()
}
#[inline]
fn machine_usize_to_isize(&self, val: u64) -> i64 {
fn target_usize_to_isize(&self, val: u64) -> i64 {
let val = val as i64;
// Now wrap-around into the machine_isize range.
if val > self.machine_isize_max() {
if val > self.target_isize_max() {
// This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into
// i64.
debug_assert!(self.pointer_size().bits() < 64);
@@ -76,11 +76,11 @@ pub trait PointerArithmetic: HasDataLayout {
let n = i.unsigned_abs();
if i >= 0 {
let (val, over) = self.overflowing_offset(val, n);
(val, over || i > self.machine_isize_max())
(val, over || i > self.target_isize_max())
} else {
let res = val.overflowing_sub(n);
let (val, over) = self.truncate_to_ptr(res);
(val, over || i < self.machine_isize_min())
(val, over || i < self.target_isize_min())
}
}

View File

@@ -75,8 +75,8 @@ impl<'tcx> ConstValue<'tcx> {
self.try_to_scalar_int()?.try_into().ok()
}
pub fn try_to_machine_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_scalar_int()?.try_to_machine_usize(tcx).ok()
pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_scalar_int()?.try_to_target_usize(tcx).ok()
}
pub fn try_to_bits_for_ty(
@@ -97,8 +97,8 @@ impl<'tcx> ConstValue<'tcx> {
ConstValue::Scalar(Scalar::from_u64(i))
}
pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
ConstValue::Scalar(Scalar::from_machine_usize(i, cx))
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
ConstValue::Scalar(Scalar::from_target_usize(i, cx))
}
}
@@ -241,7 +241,7 @@ impl<Prov> Scalar<Prov> {
}
#[inline]
pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
Self::from_uint(i, cx.data_layout().pointer_size)
}
@@ -268,7 +268,7 @@ impl<Prov> Scalar<Prov> {
}
#[inline]
pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self {
pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self {
Self::from_int(i, cx.data_layout().pointer_size)
}
@@ -429,7 +429,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized unsigned integer.
/// Fails if the scalar is a pointer.
pub fn to_machine_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
pub fn to_target_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
let b = self.to_uint(cx.data_layout().pointer_size)?;
Ok(u64::try_from(b).unwrap())
}
@@ -469,7 +469,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized signed integer.
/// Fails if the scalar is a pointer.
pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
pub fn to_target_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
let b = self.to_int(cx.data_layout().pointer_size)?;
Ok(i64::try_from(b).unwrap())
}

View File

@@ -2357,10 +2357,10 @@ impl<'tcx> ConstantKind<'tcx> {
) -> Option<u64> {
match self {
Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env),
Self::Val(val, _) => val.try_to_machine_usize(tcx),
Self::Val(val, _) => val.try_to_target_usize(tcx),
Self::Unevaluated(uneval, _) => {
match tcx.const_eval_resolve(param_env, *uneval, None) {
Ok(val) => val.try_to_machine_usize(tcx),
Ok(val) => val.try_to_target_usize(tcx),
Err(_) => None,
}
}

View File

@@ -2143,12 +2143,12 @@ rustc_queries! {
separate_provide_extern
}
query permits_uninit_init(key: ty::ParamEnvAnd<'tcx, TyAndLayout<'tcx>>) -> bool {
desc { "checking to see if `{}` permits being left uninit", key.value.ty }
query permits_uninit_init(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, ty::layout::LayoutError<'tcx>> {
desc { "checking to see if `{}` permits being left uninit", key.value }
}
query permits_zero_init(key: ty::ParamEnvAnd<'tcx, TyAndLayout<'tcx>>) -> bool {
desc { "checking to see if `{}` permits being left zeroed", key.value.ty }
query permits_zero_init(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, ty::layout::LayoutError<'tcx>> {
desc { "checking to see if `{}` permits being left zeroed", key.value }
}
query compare_impl_const(

View File

@@ -406,6 +406,7 @@ impl<'tcx> AdtDef<'tcx> {
}
/// Return the index of `VariantDef` given a variant id.
#[inline]
pub fn variant_index_with_id(self, vid: DefId) -> VariantIdx {
self.variants()
.iter_enumerated()

View File

@@ -206,7 +206,7 @@ impl<'tcx> Const<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> Option<u64> {
self.kind().eval(tcx, param_env).try_to_machine_usize(tcx)
self.kind().eval(tcx, param_env).try_to_target_usize(tcx)
}
#[inline]

View File

@@ -232,7 +232,7 @@ impl ScalarInt {
}
#[inline]
pub fn try_to_machine_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64)
}

View File

@@ -125,8 +125,8 @@ impl<'tcx> ConstKind<'tcx> {
}
#[inline]
pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_value()?.try_to_machine_usize(tcx)
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_value()?.try_to_target_usize(tcx)
}
}

View File

@@ -78,8 +78,8 @@ impl<'tcx> ValTree<'tcx> {
}
}
pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_scalar_int().map(|s| s.try_to_machine_usize(tcx).ok()).flatten()
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_scalar_int().map(|s| s.try_to_target_usize(tcx).ok()).flatten()
}
/// Get the values inside the ValTree as a slice of bytes. This only works for

View File

@@ -125,7 +125,7 @@ impl FlagComputation {
self.bound_computation(ts, |flags, ts| flags.add_tys(ts));
}
&ty::GeneratorWitnessMIR(_, ref substs) => {
ty::GeneratorWitnessMIR(_, substs) => {
let should_remove_further_specializable =
!self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
self.add_substs(substs);

View File

@@ -159,7 +159,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
match self {
Self::ConstIsZero(c) => {
let c = ty::EarlyBinder(c).subst(tcx, substs);
let pred = match c.kind().try_to_machine_usize(tcx) {
let pred = match c.kind().try_to_target_usize(tcx) {
Some(0) => Self::True,
Some(1..) => Self::False,
None => Self::ConstIsZero(c),

View File

@@ -191,7 +191,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP
// If we can evaluate the array length before having a `ParamEnv`, then
// we can simplify the predicate. This is an optimization.
Array(ty, len) => match len.kind().try_to_machine_usize(tcx) {
Array(ty, len) => match len.kind().try_to_target_usize(tcx) {
Some(0) => InhabitedPredicate::True,
Some(1..) => ty.inhabited_predicate(tcx),
None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),

View File

@@ -2429,7 +2429,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
let parent = self.parent(def_id);
if let DefKind::Impl = self.def_kind(parent) {
if let DefKind::Impl { .. } = self.def_kind(parent) {
return Some(parent);
}
}

View File

@@ -30,7 +30,6 @@ use crate::traits::specialization_graph;
use crate::traits::{self, ImplSource};
use crate::ty::context::TyCtxtFeed;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::layout::TyAndLayout;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::GeneratorDiagnosticData;

View File

@@ -167,7 +167,7 @@ impl<'tcx> TyCtxt<'tcx> {
| DefKind::Fn
| DefKind::AssocFn
| DefKind::AssocConst
| DefKind::Impl,
| DefKind::Impl { .. },
def_id,
) => Some(def_id),
Res::Err => None,

View File

@@ -22,7 +22,7 @@ pub struct CopyProp;
impl<'tcx> MirPass<'tcx> for CopyProp {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
sess.mir_opt_level() >= 4
sess.mir_opt_level() >= 1
}
#[instrument(level = "trace", skip(self, tcx, body))]
@@ -96,7 +96,7 @@ fn fully_moved_locals(ssa: &SsaLocals, body: &Body<'_>) -> BitSet<Local> {
fully_moved
}
/// Utility to help performing subtitution of `*pattern` by `target`.
/// Utility to help performing substitution of `*pattern` by `target`.
struct Replacer<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
fully_moved: BitSet<Local>,

View File

@@ -6,7 +6,8 @@ use rustc_middle::mir::{
BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
};
use rustc_middle::ty::{self, layout::TyAndLayout, ParamEnv, ParamEnvAnd, SubstsRef, Ty, TyCtxt};
use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::{self, ParamEnv, ParamEnvAnd, SubstsRef, Ty, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
pub struct InstCombine;
@@ -230,38 +231,41 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
// Check this is a foldable intrinsic before we query the layout of our generic parameter
let Some(assert_panics) = intrinsic_assert_panics(intrinsic_name) else { return; };
let Ok(layout) = self.tcx.layout_of(self.param_env.and(ty)) else { return; };
if assert_panics(self.tcx, self.param_env.and(layout)) {
match assert_panics(self.tcx, self.param_env.and(ty)) {
// We don't know the layout, don't touch the assertion
Err(_) => {}
Ok(true) => {
// If we know the assert panics, indicate to later opts that the call diverges
*target = None;
} else {
}
Ok(false) => {
// If we know the assert does not panic, turn the call into a Goto
terminator.kind = TerminatorKind::Goto { target: *target_block };
}
}
}
}
fn intrinsic_assert_panics<'tcx>(
intrinsic_name: Symbol,
) -> Option<fn(TyCtxt<'tcx>, ParamEnvAnd<'tcx, TyAndLayout<'tcx>>) -> bool> {
) -> Option<fn(TyCtxt<'tcx>, ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, LayoutError<'tcx>>> {
fn inhabited_predicate<'tcx>(
_tcx: TyCtxt<'tcx>,
param_env_and_layout: ParamEnvAnd<'tcx, TyAndLayout<'tcx>>,
) -> bool {
let (_param_env, layout) = param_env_and_layout.into_parts();
layout.abi.is_uninhabited()
tcx: TyCtxt<'tcx>,
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Result<bool, LayoutError<'tcx>> {
Ok(tcx.layout_of(param_env_and_ty)?.abi.is_uninhabited())
}
fn zero_valid_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
param_env_and_layout: ParamEnvAnd<'tcx, TyAndLayout<'tcx>>,
) -> bool {
!tcx.permits_zero_init(param_env_and_layout)
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Result<bool, LayoutError<'tcx>> {
Ok(!tcx.permits_zero_init(param_env_and_ty)?)
}
fn mem_uninitialized_valid_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
param_env_and_layout: ParamEnvAnd<'tcx, TyAndLayout<'tcx>>,
) -> bool {
!tcx.permits_uninit_init(param_env_and_layout)
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Result<bool, LayoutError<'tcx>> {
Ok(!tcx.permits_uninit_init(param_env_and_ty)?)
}
match intrinsic_name {

View File

@@ -19,6 +19,33 @@ pub struct SsaLocals {
copy_classes: IndexVec<Local, Local>,
}
/// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
/// actually compute dominators, we can just compare block indices because bb0 is always the first
/// block, and in any body all other blocks are always always dominated by bb0.
struct SmallDominators {
inner: Option<Dominators<BasicBlock>>,
}
trait DomExt {
fn dominates(self, _other: Self, dominators: &SmallDominators) -> bool;
}
impl DomExt for Location {
fn dominates(self, other: Location, dominators: &SmallDominators) -> bool {
if self.block == other.block {
self.statement_index <= other.statement_index
} else {
dominators.dominates(self.block, other.block)
}
}
}
impl SmallDominators {
fn dominates(&self, dom: BasicBlock, node: BasicBlock) -> bool {
if let Some(inner) = &self.inner { inner.dominates(dom, node) } else { dom < node }
}
}
impl SsaLocals {
pub fn new<'tcx>(
tcx: TyCtxt<'tcx>,
@@ -29,7 +56,9 @@ impl SsaLocals {
let assignment_order = Vec::new();
let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls);
let dominators = body.basic_blocks.dominators();
let dominators =
if body.basic_blocks.len() > 2 { Some(body.basic_blocks.dominators()) } else { None };
let dominators = SmallDominators { inner: dominators };
let mut visitor = SsaVisitor { assignments, assignment_order, dominators };
for (local, decl) in body.local_decls.iter_enumerated() {
@@ -41,9 +70,15 @@ impl SsaLocals {
}
}
if body.basic_blocks.len() > 2 {
for (bb, data) in traversal::reverse_postorder(body) {
visitor.visit_basic_block_data(bb, data);
}
} else {
for (bb, data) in body.basic_blocks.iter_enumerated() {
visitor.visit_basic_block_data(bb, data);
}
}
for var_debug_info in &body.var_debug_info {
visitor.visit_var_debug_info(var_debug_info);
@@ -139,7 +174,7 @@ enum LocationExtended {
}
struct SsaVisitor {
dominators: Dominators<BasicBlock>,
dominators: SmallDominators,
assignments: IndexVec<Local, Set1<LocationExtended>>,
assignment_order: Vec<Local>,
}

View File

@@ -1191,30 +1191,16 @@ impl<'v> RootCollector<'_, 'v> {
fn process_item(&mut self, id: hir::ItemId) {
match self.tcx.def_kind(id.owner_id) {
DefKind::Enum | DefKind::Struct | DefKind::Union => {
let item = self.tcx.hir().item(id);
match item.kind {
hir::ItemKind::Enum(_, ref generics)
| hir::ItemKind::Struct(_, ref generics)
| hir::ItemKind::Union(_, ref generics) => {
if generics.params.is_empty() {
if self.mode == MonoItemCollectionMode::Eager {
debug!(
"RootCollector: ADT drop-glue for {}",
self.tcx.def_path_str(item.owner_id.to_def_id())
);
if self.mode == MonoItemCollectionMode::Eager
&& self.tcx.generics_of(id.owner_id).count() == 0
{
debug!("RootCollector: ADT drop-glue for `{id:?}`",);
let ty = Instance::new(
item.owner_id.to_def_id(),
InternalSubsts::empty(),
)
.ty(self.tcx, ty::ParamEnv::reveal_all());
let ty =
self.tcx.bound_type_of(id.owner_id.to_def_id()).no_bound_vars().unwrap();
visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
}
}
}
_ => bug!(),
}
}
DefKind::GlobalAsm => {
debug!(
"RootCollector: ItemKind::GlobalAsm({})",
@@ -1238,10 +1224,9 @@ impl<'v> RootCollector<'_, 'v> {
collect_const_value(self.tcx, val, &mut self.output);
}
}
DefKind::Impl => {
DefKind::Impl { .. } => {
if self.mode == MonoItemCollectionMode::Eager {
let item = self.tcx.hir().item(id);
create_mono_items_for_default_impls(self.tcx, item, self.output);
create_mono_items_for_default_impls(self.tcx, id, self.output);
}
}
DefKind::Fn => {
@@ -1326,32 +1311,25 @@ fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
generics.requires_monomorphization(tcx)
}
#[instrument(level = "debug", skip(tcx, output))]
fn create_mono_items_for_default_impls<'tcx>(
tcx: TyCtxt<'tcx>,
item: &'tcx hir::Item<'tcx>,
item: hir::ItemId,
output: &mut MonoItems<'tcx>,
) {
match item.kind {
hir::ItemKind::Impl(ref impl_) => {
if matches!(impl_.polarity, hir::ImplPolarity::Negative(_)) {
let polarity = tcx.impl_polarity(item.owner_id);
if matches!(polarity, ty::ImplPolarity::Negative) {
return;
}
for param in impl_.generics.params {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {}
hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => {
if tcx.generics_of(item.owner_id).own_requires_monomorphization() {
return;
}
}
}
debug!(
"create_mono_items_for_default_impls(item={})",
tcx.def_path_str(item.owner_id.to_def_id())
);
let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else {
return;
};
if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
let trait_ref = trait_ref.subst_identity();
let param_env = ty::ParamEnv::reveal_all();
@@ -1366,27 +1344,19 @@ fn create_mono_items_for_default_impls<'tcx>(
continue;
}
let substs =
InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
GenericParamDefKind::Type { .. }
| GenericParamDefKind::Const { .. } => {
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
trait_ref.substs[param.index as usize]
}
});
let instance =
ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance)
{
if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance) {
output.push(mono_item);
}
}
}
}
_ => bug!(),
}
}
/// Scans the miri alloc in order to find function calls, closures, and drop-glue.

View File

@@ -172,7 +172,7 @@ fn mark_used_by_default_parameters<'tcx>(
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
| DefKind::Impl => {
| DefKind::Impl { .. } => {
for param in &generics.params {
debug!(?param, "(other)");
if let ty::GenericParamDefKind::Lifetime = param.kind {

View File

@@ -526,10 +526,8 @@ fn check_item<'tcx>(
}
}
}
DefKind::Impl => {
let of_trait = tcx.impl_trait_ref(id.owner_id);
if of_trait.is_some() {
DefKind::Impl { of_trait } => {
if of_trait {
worklist.push(id.owner_id.def_id);
}
@@ -541,7 +539,7 @@ fn check_item<'tcx>(
// And we access the Map here to get HirId from LocalDefId
for id in local_def_ids {
if of_trait.is_some() || has_allow_dead_code_or_lang_attr(tcx, id) {
if of_trait || has_allow_dead_code_or_lang_attr(tcx, id) {
worklist.push(id);
}
}

View File

@@ -145,7 +145,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
// Don't run unused pass for #[derive()]
let parent = tcx.local_parent(local_def_id);
if let DefKind::Impl = tcx.def_kind(parent)
if let DefKind::Impl { .. } = tcx.def_kind(parent)
&& tcx.has_attr(parent.to_def_id(), sym::automatically_derived)
{
return;

View File

@@ -320,19 +320,19 @@ fn check_item<'tcx>(
worklist.push(id.owner_id.def_id);
}
if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: true }) {
return;
}
// We need only trait impls here, not inherent impls, and only non-exported ones
let item = tcx.hir().item(id);
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) =
item.kind
{
if !effective_visibilities.is_reachable(item.owner_id.def_id) {
worklist.extend(items.iter().map(|ii_ref| ii_ref.id.owner_id.def_id));
if effective_visibilities.is_reachable(id.owner_id.def_id) {
return;
}
let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else {
let items = tcx.associated_item_def_ids(id.owner_id);
worklist.extend(items.iter().map(|ii_ref| ii_ref.expect_local()));
let Some(trait_def_id) = tcx.trait_id_of_impl(id.owner_id.to_def_id()) else {
unreachable!();
};
@@ -340,11 +340,8 @@ fn check_item<'tcx>(
return;
}
worklist.extend(
tcx.provided_trait_methods(trait_def_id).map(|assoc| assoc.def_id.expect_local()),
);
}
}
worklist
.extend(tcx.provided_trait_methods(trait_def_id).map(|assoc| assoc.def_id.expect_local()));
}
fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {

View File

@@ -593,7 +593,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
| DefKind::InlineConst
| DefKind::Field
| DefKind::GlobalAsm
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::Closure
| DefKind::Generator => (),
}
@@ -1997,7 +1997,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
// Subitems of inherent impls have their own publicity.
// A trait impl is public when both its type and its trait are public
// Subitems of trait impls have inherited publicity.
DefKind::Impl => {
DefKind::Impl { .. } => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Impl(ref impl_) = item.kind {
let impl_vis =

View File

@@ -92,7 +92,7 @@ where
let mut lock = self.cache.lock();
// We may be overwriting another value. This is all right, since the dep-graph
// will check that the fingerprint matches.
lock.insert(key, (value.clone(), index));
lock.insert(key, (value, index));
value
}
@@ -153,7 +153,7 @@ where
#[inline]
fn complete(&self, _key: (), value: V, index: DepNodeIndex) -> Self::Stored {
*self.cache.lock() = Some((value.clone(), index));
*self.cache.lock() = Some((value, index));
value
}
@@ -283,7 +283,7 @@ where
let mut lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
#[cfg(not(parallel_compiler))]
let mut lock = self.cache.lock();
lock.insert(key, (value.clone(), index));
lock.insert(key, (value, index));
value
}

View File

@@ -987,7 +987,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
| DefKind::LifetimeParam
| DefKind::GlobalAsm
| DefKind::Closure
| DefKind::Impl
| DefKind::Impl { .. }
| DefKind::Generator,
_,
)

View File

@@ -1,21 +0,0 @@
[package]
name = "rustc_save_analysis"
version = "0.0.0"
edition = "2021"
[dependencies]
tracing = "0.1"
rustc_middle = { path = "../rustc_middle" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
serde_json = "1"
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rls-data = "0.19"
rls-span = "0.5"

File diff suppressed because it is too large Load Diff

View File

@@ -1,91 +0,0 @@
use rls_data::config::Config;
use rls_data::{
self, Analysis, CompilationOptions, CratePreludeData, Def, DefKind, Impl, Import, MacroRef,
Ref, RefKind, Relation,
};
use rls_span::{Column, Row};
#[derive(Debug)]
pub struct Access {
pub reachable: bool,
pub public: bool,
}
pub struct Dumper {
result: Analysis,
config: Config,
}
impl Dumper {
pub fn new(config: Config) -> Dumper {
Dumper { config: config.clone(), result: Analysis::new(config) }
}
pub fn analysis(&self) -> &Analysis {
&self.result
}
}
impl Dumper {
pub fn crate_prelude(&mut self, data: CratePreludeData) {
self.result.prelude = Some(data)
}
pub fn compilation_opts(&mut self, data: CompilationOptions) {
self.result.compilation = Some(data);
}
pub fn _macro_use(&mut self, data: MacroRef) {
if self.config.pub_only || self.config.reachable_only {
return;
}
self.result.macro_refs.push(data);
}
pub fn import(&mut self, access: &Access, import: Import) {
if !access.public && self.config.pub_only || !access.reachable && self.config.reachable_only
{
return;
}
self.result.imports.push(import);
}
pub fn dump_ref(&mut self, data: Ref) {
if self.config.pub_only || self.config.reachable_only {
return;
}
self.result.refs.push(data);
}
pub fn dump_def(&mut self, access: &Access, mut data: Def) {
if !access.public && self.config.pub_only || !access.reachable && self.config.reachable_only
{
return;
}
if data.kind == DefKind::Mod && data.span.file_name.to_str().unwrap() != data.value {
// If the module is an out-of-line definition, then we'll make the
// definition the first character in the module's file and turn
// the declaration into a reference to it.
let rf = Ref { kind: RefKind::Mod, span: data.span, ref_id: data.id };
self.result.refs.push(rf);
data.span = rls_data::SpanData {
file_name: data.value.clone().into(),
byte_start: 0,
byte_end: 0,
line_start: Row::new_one_indexed(1),
line_end: Row::new_one_indexed(1),
column_start: Column::new_one_indexed(1),
column_end: Column::new_one_indexed(1),
}
}
self.result.defs.push(data);
}
pub fn dump_relation(&mut self, data: Relation) {
self.result.relations.push(data);
}
pub fn dump_impl(&mut self, data: Impl) {
self.result.impls.push(data);
}
}

View File

@@ -1,10 +0,0 @@
use rustc_macros::Diagnostic;
use std::path::Path;
#[derive(Diagnostic)]
#[diag(save_analysis_could_not_open)]
pub(crate) struct CouldNotOpen<'a> {
pub file_name: &'a Path,
pub err: std::io::Error,
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,931 +0,0 @@
// A signature is a string representation of an item's type signature, excluding
// any body. It also includes ids for any defs or refs in the signature. For
// example:
//
// ```
// fn foo(x: String) {
// println!("{}", x);
// }
// ```
// The signature string is something like "fn foo(x: String) {}" and the signature
// will have defs for `foo` and `x` and a ref for `String`.
//
// All signature text should parse in the correct context (i.e., in a module or
// impl, etc.). Clients may want to trim trailing `{}` or `;`. The text of a
// signature is not guaranteed to be stable (it may improve or change as the
// syntax changes, or whitespace or punctuation may change). It is also likely
// not to be pretty - no attempt is made to prettify the text. It is recommended
// that clients run the text through Rustfmt.
//
// This module generates Signatures for items by walking the AST and looking up
// references.
//
// Signatures do not include visibility info. I'm not sure if this is a feature
// or an omission (FIXME).
//
// FIXME where clauses need implementing, defs/refs in generics are mostly missing.
use crate::{id_from_def_id, SaveContext};
use rls_data::{SigElement, Signature};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir_pretty::id_to_string;
use rustc_hir_pretty::{bounds_to_string, path_segment_to_string, path_to_string, ty_to_string};
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{Ident, Symbol};
pub fn item_signature(item: &hir::Item<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
item.make(0, None, scx).ok()
}
pub fn foreign_item_signature(
item: &hir::ForeignItem<'_>,
scx: &SaveContext<'_>,
) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
item.make(0, None, scx).ok()
}
/// Signature for a struct or tuple field declaration.
/// Does not include a trailing comma.
pub fn field_signature(field: &hir::FieldDef<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
field.make(0, None, scx).ok()
}
/// Does not include a trailing comma.
pub fn variant_signature(variant: &hir::Variant<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
variant.make(0, None, scx).ok()
}
pub fn method_signature(
id: hir::OwnerId,
ident: Ident,
generics: &hir::Generics<'_>,
m: &hir::FnSig<'_>,
scx: &SaveContext<'_>,
) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
make_method_signature(id, ident, generics, m, scx).ok()
}
pub fn assoc_const_signature(
id: hir::OwnerId,
ident: Symbol,
ty: &hir::Ty<'_>,
default: Option<&hir::Expr<'_>>,
scx: &SaveContext<'_>,
) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
make_assoc_const_signature(id, ident, ty, default, scx).ok()
}
pub fn assoc_type_signature(
id: hir::OwnerId,
ident: Ident,
bounds: Option<hir::GenericBounds<'_>>,
default: Option<&hir::Ty<'_>>,
scx: &SaveContext<'_>,
) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
make_assoc_type_signature(id, ident, bounds, default, scx).ok()
}
type Result = std::result::Result<Signature, &'static str>;
trait Sig {
type Parent;
fn make(&self, offset: usize, id: Option<Self::Parent>, scx: &SaveContext<'_>) -> Result;
}
fn extend_sig(
mut sig: Signature,
text: String,
defs: Vec<SigElement>,
refs: Vec<SigElement>,
) -> Signature {
sig.text = text;
sig.defs.extend(defs.into_iter());
sig.refs.extend(refs.into_iter());
sig
}
fn replace_text(mut sig: Signature, text: String) -> Signature {
sig.text = text;
sig
}
fn merge_sigs(text: String, sigs: Vec<Signature>) -> Signature {
let mut result = Signature { text, defs: vec![], refs: vec![] };
let (defs, refs): (Vec<_>, Vec<_>) = sigs.into_iter().map(|s| (s.defs, s.refs)).unzip();
result.defs.extend(defs.into_iter().flat_map(|ds| ds.into_iter()));
result.refs.extend(refs.into_iter().flat_map(|rs| rs.into_iter()));
result
}
fn text_sig(text: String) -> Signature {
Signature { text, defs: vec![], refs: vec![] }
}
impl<'hir> Sig for hir::Ty<'hir> {
type Parent = hir::HirId;
fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
let id = Some(self.hir_id);
match self.kind {
hir::TyKind::Slice(ref ty) => {
let nested = ty.make(offset + 1, id, scx)?;
let text = format!("[{}]", nested.text);
Ok(replace_text(nested, text))
}
hir::TyKind::Ptr(ref mt) => {
let prefix = match mt.mutbl {
hir::Mutability::Mut => "*mut ",
hir::Mutability::Not => "*const ",
};
let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
let text = format!("{}{}", prefix, nested.text);
Ok(replace_text(nested, text))
}
hir::TyKind::Ref(ref lifetime, ref mt) => {
let mut prefix = "&".to_owned();
prefix.push_str(&lifetime.ident.to_string());
prefix.push(' ');
if mt.mutbl.is_mut() {
prefix.push_str("mut ");
};
let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
let text = format!("{}{}", prefix, nested.text);
Ok(replace_text(nested, text))
}
hir::TyKind::Never => Ok(text_sig("!".to_owned())),
hir::TyKind::Tup(ts) => {
let mut text = "(".to_owned();
let mut defs = vec![];
let mut refs = vec![];
for t in ts {
let nested = t.make(offset + text.len(), id, scx)?;
text.push_str(&nested.text);
text.push(',');
defs.extend(nested.defs.into_iter());
refs.extend(nested.refs.into_iter());
}
text.push(')');
Ok(Signature { text, defs, refs })
}
hir::TyKind::BareFn(ref f) => {
let mut text = String::new();
if !f.generic_params.is_empty() {
// FIXME defs, bounds on lifetimes
text.push_str("for<");
text.push_str(
&f.generic_params
.iter()
.filter_map(|param| match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
Some(param.name.ident().to_string())
}
_ => None,
})
.collect::<Vec<_>>()
.join(", "),
);
text.push('>');
}
if let hir::Unsafety::Unsafe = f.unsafety {
text.push_str("unsafe ");
}
text.push_str("fn(");
let mut defs = vec![];
let mut refs = vec![];
for i in f.decl.inputs {
let nested = i.make(offset + text.len(), Some(i.hir_id), scx)?;
text.push_str(&nested.text);
text.push(',');
defs.extend(nested.defs.into_iter());
refs.extend(nested.refs.into_iter());
}
text.push(')');
if let hir::FnRetTy::Return(ref t) = f.decl.output {
text.push_str(" -> ");
let nested = t.make(offset + text.len(), None, scx)?;
text.push_str(&nested.text);
text.push(',');
defs.extend(nested.defs.into_iter());
refs.extend(nested.refs.into_iter());
}
Ok(Signature { text, defs, refs })
}
hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.make(offset, id, scx),
hir::TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref path)) => {
let nested_ty = qself.make(offset + 1, id, scx)?;
let prefix = format!(
"<{} as {}>::",
nested_ty.text,
path_segment_to_string(&path.segments[0])
);
let name = path_segment_to_string(path.segments.last().ok_or("Bad path")?);
let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
let id = id_from_def_id(res.def_id());
if path.segments.len() == 2 {
let start = offset + prefix.len();
let end = start + name.len();
Ok(Signature {
text: prefix + &name,
defs: vec![],
refs: vec![SigElement { id, start, end }],
})
} else {
let start = offset + prefix.len() + 5;
let end = start + name.len();
// FIXME should put the proper path in there, not ellipsis.
Ok(Signature {
text: prefix + "...::" + &name,
defs: vec![],
refs: vec![SigElement { id, start, end }],
})
}
}
hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => {
let nested_ty = ty.make(offset + 1, id, scx)?;
let prefix = format!("<{}>::", nested_ty.text);
let name = path_segment_to_string(segment);
let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
let id = id_from_def_id(res.def_id());
let start = offset + prefix.len();
let end = start + name.len();
Ok(Signature {
text: prefix + &name,
defs: vec![],
refs: vec![SigElement { id, start, end }],
})
}
hir::TyKind::Path(hir::QPath::LangItem(lang_item, _, _)) => {
Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name())))
}
hir::TyKind::TraitObject(bounds, ..) => {
// FIXME recurse into bounds
let bounds: Vec<hir::GenericBound<'_>> = bounds
.iter()
.map(|hir::PolyTraitRef { bound_generic_params, trait_ref, span }| {
hir::GenericBound::Trait(
hir::PolyTraitRef {
bound_generic_params,
trait_ref: hir::TraitRef {
path: trait_ref.path,
hir_ref_id: trait_ref.hir_ref_id,
},
span: *span,
},
hir::TraitBoundModifier::None,
)
})
.collect();
let nested = bounds_to_string(&bounds);
Ok(text_sig(nested))
}
hir::TyKind::Array(ref ty, ref length) => {
let nested_ty = ty.make(offset + 1, id, scx)?;
let expr = id_to_string(&scx.tcx.hir(), length.hir_id()).replace('\n', " ");
let text = format!("[{}; {}]", nested_ty.text, expr);
Ok(replace_text(nested_ty, text))
}
hir::TyKind::OpaqueDef(item_id, _, _) => {
let item = scx.tcx.hir().item(item_id);
item.make(offset, Some(item_id.hir_id()), scx)
}
hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"),
}
}
}
impl<'hir> Sig for hir::Item<'hir> {
type Parent = hir::HirId;
fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
let id = Some(self.hir_id());
match self.kind {
hir::ItemKind::Static(ref ty, m, ref body) => {
let mut text = "static ".to_owned();
if m.is_mut() {
text.push_str("mut ");
}
let name = self.ident.to_string();
let defs = vec![SigElement {
id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
text.push_str(&name);
text.push_str(": ");
let ty = ty.make(offset + text.len(), id, scx)?;
text.push_str(&ty.text);
text.push_str(" = ");
let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
text.push_str(&expr);
text.push(';');
Ok(extend_sig(ty, text, defs, vec![]))
}
hir::ItemKind::Const(ref ty, ref body) => {
let mut text = "const ".to_owned();
let name = self.ident.to_string();
let defs = vec![SigElement {
id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
text.push_str(&name);
text.push_str(": ");
let ty = ty.make(offset + text.len(), id, scx)?;
text.push_str(&ty.text);
text.push_str(" = ");
let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
text.push_str(&expr);
text.push(';');
Ok(extend_sig(ty, text, defs, vec![]))
}
hir::ItemKind::Fn(hir::FnSig { ref decl, header, span: _ }, ref generics, _) => {
let mut text = String::new();
if let hir::Constness::Const = header.constness {
text.push_str("const ");
}
if hir::IsAsync::Async == header.asyncness {
text.push_str("async ");
}
if let hir::Unsafety::Unsafe = header.unsafety {
text.push_str("unsafe ");
}
text.push_str("fn ");
let mut sig =
name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push('(');
for i in decl.inputs {
// FIXME should descend into patterns to add defs.
sig.text.push_str(": ");
let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
sig.text.push_str(&nested.text);
sig.text.push(',');
sig.defs.extend(nested.defs.into_iter());
sig.refs.extend(nested.refs.into_iter());
}
sig.text.push(')');
if let hir::FnRetTy::Return(ref t) = decl.output {
sig.text.push_str(" -> ");
let nested = t.make(offset + sig.text.len(), None, scx)?;
sig.text.push_str(&nested.text);
sig.defs.extend(nested.defs.into_iter());
sig.refs.extend(nested.refs.into_iter());
}
sig.text.push_str(" {}");
Ok(sig)
}
hir::ItemKind::Macro(..) => {
let mut text = "macro".to_owned();
let name = self.ident.to_string();
text.push_str(&name);
text.push_str(&"! {}");
Ok(text_sig(text))
}
hir::ItemKind::Mod(ref _mod) => {
let mut text = "mod ".to_owned();
let name = self.ident.to_string();
let defs = vec![SigElement {
id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
text.push_str(&name);
// Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
text.push(';');
Ok(Signature { text, defs, refs: vec![] })
}
hir::ItemKind::TyAlias(ref ty, ref generics) => {
let text = "type ".to_owned();
let mut sig =
name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push_str(" = ");
let ty = ty.make(offset + sig.text.len(), id, scx)?;
sig.text.push_str(&ty.text);
sig.text.push(';');
Ok(merge_sigs(sig.text.clone(), vec![sig, ty]))
}
hir::ItemKind::Enum(_, ref generics) => {
let text = "enum ".to_owned();
let mut sig =
name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push_str(" {}");
Ok(sig)
}
hir::ItemKind::Struct(_, ref generics) => {
let text = "struct ".to_owned();
let mut sig =
name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push_str(" {}");
Ok(sig)
}
hir::ItemKind::Union(_, ref generics) => {
let text = "union ".to_owned();
let mut sig =
name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push_str(" {}");
Ok(sig)
}
hir::ItemKind::Trait(is_auto, unsafety, ref generics, bounds, _) => {
let mut text = String::new();
if is_auto == hir::IsAuto::Yes {
text.push_str("auto ");
}
if let hir::Unsafety::Unsafe = unsafety {
text.push_str("unsafe ");
}
text.push_str("trait ");
let mut sig =
name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
if !bounds.is_empty() {
sig.text.push_str(": ");
sig.text.push_str(&bounds_to_string(bounds));
}
// FIXME where clause
sig.text.push_str(" {}");
Ok(sig)
}
hir::ItemKind::TraitAlias(ref generics, bounds) => {
let mut text = String::new();
text.push_str("trait ");
let mut sig =
name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
if !bounds.is_empty() {
sig.text.push_str(" = ");
sig.text.push_str(&bounds_to_string(bounds));
}
// FIXME where clause
sig.text.push(';');
Ok(sig)
}
hir::ItemKind::Impl(hir::Impl {
unsafety,
polarity,
defaultness,
defaultness_span: _,
constness,
ref generics,
ref of_trait,
ref self_ty,
items: _,
}) => {
let mut text = String::new();
if let hir::Defaultness::Default { .. } = defaultness {
text.push_str("default ");
}
if let hir::Unsafety::Unsafe = unsafety {
text.push_str("unsafe ");
}
text.push_str("impl");
if let hir::Constness::Const = constness {
text.push_str(" const");
}
let generics_sig =
generics.make(offset + text.len(), Some(self.owner_id.def_id), scx)?;
text.push_str(&generics_sig.text);
text.push(' ');
let trait_sig = if let Some(ref t) = *of_trait {
if let hir::ImplPolarity::Negative(_) = polarity {
text.push('!');
}
let trait_sig = t.path.make(offset + text.len(), id, scx)?;
text.push_str(&trait_sig.text);
text.push_str(" for ");
trait_sig
} else {
text_sig(String::new())
};
let ty_sig = self_ty.make(offset + text.len(), id, scx)?;
text.push_str(&ty_sig.text);
text.push_str(" {}");
Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig]))
// FIXME where clause
}
hir::ItemKind::ForeignMod { .. } => Err("extern mod"),
hir::ItemKind::GlobalAsm(_) => Err("global asm"),
hir::ItemKind::ExternCrate(_) => Err("extern crate"),
hir::ItemKind::OpaqueTy(ref opaque) => {
if opaque.in_trait {
Err("opaque type in trait")
} else {
Err("opaque type")
}
}
// FIXME should implement this (e.g., pub use).
hir::ItemKind::Use(..) => Err("import"),
}
}
}
impl<'hir> Sig for hir::Path<'hir> {
type Parent = hir::HirId;
fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
let (name, start, end) = match res {
Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => {
return Ok(Signature { text: path_to_string(self), defs: vec![], refs: vec![] });
}
Res::Def(DefKind::AssocConst | DefKind::Variant | DefKind::Ctor(..), _) => {
let len = self.segments.len();
if len < 2 {
return Err("Bad path");
}
// FIXME: really we should descend into the generics here and add SigElements for
// them.
// FIXME: would be nice to have a def for the first path segment.
let seg1 = path_segment_to_string(&self.segments[len - 2]);
let seg2 = path_segment_to_string(&self.segments[len - 1]);
let start = offset + seg1.len() + 2;
(format!("{}::{}", seg1, seg2), start, start + seg2.len())
}
_ => {
let name = path_segment_to_string(self.segments.last().ok_or("Bad path")?);
let end = offset + name.len();
(name, offset, end)
}
};
let id = id_from_def_id(res.def_id());
Ok(Signature { text: name, defs: vec![], refs: vec![SigElement { id, start, end }] })
}
}
// This does not cover the where clause, which must be processed separately.
impl<'hir> Sig for hir::Generics<'hir> {
type Parent = LocalDefId;
fn make(&self, offset: usize, _parent_id: Option<LocalDefId>, scx: &SaveContext<'_>) -> Result {
if self.params.is_empty() {
return Ok(text_sig(String::new()));
}
let mut text = "<".to_owned();
let mut defs = Vec::with_capacity(self.params.len());
for param in self.params {
let mut param_text = String::new();
if let hir::GenericParamKind::Const { .. } = param.kind {
param_text.push_str("const ");
}
param_text.push_str(param.name.ident().as_str());
defs.push(SigElement {
id: id_from_def_id(param.def_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + param_text.as_str().len(),
});
if let hir::GenericParamKind::Const { ref ty, default } = param.kind {
param_text.push_str(": ");
param_text.push_str(&ty_to_string(&ty));
if let Some(default) = default {
param_text.push_str(" = ");
param_text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
}
}
text.push_str(&param_text);
text.push(',');
}
text.push('>');
Ok(Signature { text, defs, refs: vec![] })
}
}
impl<'hir> Sig for hir::FieldDef<'hir> {
type Parent = LocalDefId;
fn make(&self, offset: usize, _parent_id: Option<LocalDefId>, scx: &SaveContext<'_>) -> Result {
let mut text = String::new();
text.push_str(&self.ident.to_string());
let defs = Some(SigElement {
id: id_from_def_id(self.def_id.to_def_id()),
start: offset,
end: offset + text.len(),
});
text.push_str(": ");
let mut ty_sig = self.ty.make(offset + text.len(), Some(self.hir_id), scx)?;
text.push_str(&ty_sig.text);
ty_sig.text = text;
ty_sig.defs.extend(defs.into_iter());
Ok(ty_sig)
}
}
impl<'hir> Sig for hir::Variant<'hir> {
type Parent = LocalDefId;
fn make(&self, offset: usize, parent_id: Option<LocalDefId>, scx: &SaveContext<'_>) -> Result {
let mut text = self.ident.to_string();
match self.data {
hir::VariantData::Struct(fields, r) => {
let id = parent_id.ok_or("Missing id for Variant's parent")?;
let name_def = SigElement {
id: id_from_def_id(id.to_def_id()),
start: offset,
end: offset + text.len(),
};
text.push_str(" { ");
let mut defs = vec![name_def];
let mut refs = vec![];
if r {
text.push_str("/* parse error */ ");
} else {
for f in fields {
let field_sig = f.make(offset + text.len(), Some(id), scx)?;
text.push_str(&field_sig.text);
text.push_str(", ");
defs.extend(field_sig.defs.into_iter());
refs.extend(field_sig.refs.into_iter());
}
}
text.push('}');
Ok(Signature { text, defs, refs })
}
hir::VariantData::Tuple(fields, _, def_id) => {
let name_def = SigElement {
id: id_from_def_id(def_id.to_def_id()),
start: offset,
end: offset + text.len(),
};
text.push('(');
let mut defs = vec![name_def];
let mut refs = vec![];
for f in fields {
let field_sig = f.make(offset + text.len(), Some(def_id), scx)?;
text.push_str(&field_sig.text);
text.push_str(", ");
defs.extend(field_sig.defs.into_iter());
refs.extend(field_sig.refs.into_iter());
}
text.push(')');
Ok(Signature { text, defs, refs })
}
hir::VariantData::Unit(_, def_id) => {
let name_def = SigElement {
id: id_from_def_id(def_id.to_def_id()),
start: offset,
end: offset + text.len(),
};
Ok(Signature { text, defs: vec![name_def], refs: vec![] })
}
}
}
}
impl<'hir> Sig for hir::ForeignItem<'hir> {
type Parent = hir::HirId;
fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
let id = Some(self.hir_id());
match self.kind {
hir::ForeignItemKind::Fn(decl, _, ref generics) => {
let mut text = String::new();
text.push_str("fn ");
let mut sig =
name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
sig.text.push('(');
for i in decl.inputs {
sig.text.push_str(": ");
let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
sig.text.push_str(&nested.text);
sig.text.push(',');
sig.defs.extend(nested.defs.into_iter());
sig.refs.extend(nested.refs.into_iter());
}
sig.text.push(')');
if let hir::FnRetTy::Return(ref t) = decl.output {
sig.text.push_str(" -> ");
let nested = t.make(offset + sig.text.len(), None, scx)?;
sig.text.push_str(&nested.text);
sig.defs.extend(nested.defs.into_iter());
sig.refs.extend(nested.refs.into_iter());
}
sig.text.push(';');
Ok(sig)
}
hir::ForeignItemKind::Static(ref ty, m) => {
let mut text = "static ".to_owned();
text.push_str(m.prefix_str());
let name = self.ident.to_string();
let defs = vec![SigElement {
id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
text.push_str(&name);
text.push_str(": ");
let ty_sig = ty.make(offset + text.len(), id, scx)?;
text.push(';');
Ok(extend_sig(ty_sig, text, defs, vec![]))
}
hir::ForeignItemKind::Type => {
let mut text = "type ".to_owned();
let name = self.ident.to_string();
let defs = vec![SigElement {
id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
text.push_str(&name);
text.push(';');
Ok(Signature { text, defs, refs: vec![] })
}
}
}
}
fn name_and_generics(
mut text: String,
offset: usize,
generics: &hir::Generics<'_>,
id: hir::OwnerId,
name: Ident,
scx: &SaveContext<'_>,
) -> Result {
let name = name.to_string();
let def = SigElement {
id: id_from_def_id(id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
};
text.push_str(&name);
let generics: Signature = generics.make(offset + text.len(), Some(id.def_id), scx)?;
// FIXME where clause
let text = format!("{}{}", text, generics.text);
Ok(extend_sig(generics, text, vec![def], vec![]))
}
fn make_assoc_type_signature(
id: hir::OwnerId,
ident: Ident,
bounds: Option<hir::GenericBounds<'_>>,
default: Option<&hir::Ty<'_>>,
scx: &SaveContext<'_>,
) -> Result {
let mut text = "type ".to_owned();
let name = ident.to_string();
let mut defs = vec![SigElement {
id: id_from_def_id(id.to_def_id()),
start: text.len(),
end: text.len() + name.len(),
}];
let mut refs = vec![];
text.push_str(&name);
if let Some(bounds) = bounds {
text.push_str(": ");
// FIXME should descend into bounds
text.push_str(&bounds_to_string(bounds));
}
if let Some(default) = default {
text.push_str(" = ");
let ty_sig = default.make(text.len(), Some(id.into()), scx)?;
text.push_str(&ty_sig.text);
defs.extend(ty_sig.defs.into_iter());
refs.extend(ty_sig.refs.into_iter());
}
text.push(';');
Ok(Signature { text, defs, refs })
}
fn make_assoc_const_signature(
id: hir::OwnerId,
ident: Symbol,
ty: &hir::Ty<'_>,
default: Option<&hir::Expr<'_>>,
scx: &SaveContext<'_>,
) -> Result {
let mut text = "const ".to_owned();
let name = ident.to_string();
let mut defs = vec![SigElement {
id: id_from_def_id(id.to_def_id()),
start: text.len(),
end: text.len() + name.len(),
}];
let mut refs = vec![];
text.push_str(&name);
text.push_str(": ");
let ty_sig = ty.make(text.len(), Some(id.into()), scx)?;
text.push_str(&ty_sig.text);
defs.extend(ty_sig.defs.into_iter());
refs.extend(ty_sig.refs.into_iter());
if let Some(default) = default {
text.push_str(" = ");
text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
}
text.push(';');
Ok(Signature { text, defs, refs })
}
fn make_method_signature(
id: hir::OwnerId,
ident: Ident,
generics: &hir::Generics<'_>,
m: &hir::FnSig<'_>,
scx: &SaveContext<'_>,
) -> Result {
// FIXME code dup with function signature
let mut text = String::new();
if let hir::Constness::Const = m.header.constness {
text.push_str("const ");
}
if hir::IsAsync::Async == m.header.asyncness {
text.push_str("async ");
}
if let hir::Unsafety::Unsafe = m.header.unsafety {
text.push_str("unsafe ");
}
text.push_str("fn ");
let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
sig.text.push('(');
for i in m.decl.inputs {
sig.text.push_str(": ");
let nested = i.make(sig.text.len(), Some(i.hir_id), scx)?;
sig.text.push_str(&nested.text);
sig.text.push(',');
sig.defs.extend(nested.defs.into_iter());
sig.refs.extend(nested.refs.into_iter());
}
sig.text.push(')');
if let hir::FnRetTy::Return(ref t) = m.decl.output {
sig.text.push_str(" -> ");
let nested = t.make(sig.text.len(), None, scx)?;
sig.text.push_str(&nested.text);
sig.defs.extend(nested.defs.into_iter());
sig.refs.extend(nested.refs.into_iter());
}
sig.text.push_str(" {}");
Ok(sig)
}

View File

@@ -1,96 +0,0 @@
use crate::generated_code;
use rustc_data_structures::sync::Lrc;
use rustc_lexer::{tokenize, TokenKind};
use rustc_session::Session;
use rustc_span::*;
#[derive(Clone)]
pub struct SpanUtils<'a> {
pub sess: &'a Session,
}
impl<'a> SpanUtils<'a> {
pub fn new(sess: &'a Session) -> SpanUtils<'a> {
SpanUtils { sess }
}
pub fn make_filename_string(&self, file: &SourceFile) -> String {
match &file.name {
FileName::Real(RealFileName::LocalPath(path)) => {
if path.is_absolute() {
self.sess.source_map().path_mapping().map_prefix(path).0.display().to_string()
} else {
self.sess
.opts
.working_dir
.remapped_path_if_available()
.join(&path)
.display()
.to_string()
}
}
filename => filename.prefer_remapped().to_string(),
}
}
pub fn snippet(&self, span: Span) -> String {
match self.sess.source_map().span_to_snippet(span) {
Ok(s) => s,
Err(_) => String::new(),
}
}
/// Finds the span of `*` token withing the larger `span`.
pub fn sub_span_of_star(&self, mut span: Span) -> Option<Span> {
let begin = self.sess.source_map().lookup_byte_offset(span.lo());
let end = self.sess.source_map().lookup_byte_offset(span.hi());
// Make the range zero-length if the span is invalid.
if begin.sf.start_pos != end.sf.start_pos {
span = span.shrink_to_lo();
}
let sf = Lrc::clone(&begin.sf);
self.sess.source_map().ensure_source_file_source_present(Lrc::clone(&sf));
let src =
sf.src.clone().or_else(|| sf.external_src.borrow().get_source().map(Lrc::clone))?;
let to_index = |pos: BytePos| -> usize { (pos - sf.start_pos).0 as usize };
let text = &src[to_index(span.lo())..to_index(span.hi())];
let start_pos = {
let mut pos = 0;
tokenize(text)
.map(|token| {
let start = pos;
pos += token.len;
(start, token)
})
.find(|(_pos, token)| token.kind == TokenKind::Star)?
.0
};
let lo = span.lo() + BytePos(start_pos as u32);
let hi = lo + BytePos(1);
Some(span.with_lo(lo).with_hi(hi))
}
/// Return true if the span is generated code, and
/// it is not a subspan of the root callsite.
///
/// Used to filter out spans of minimal value,
/// such as references to macro internal variables.
pub fn filter_generated(&self, span: Span) -> bool {
if generated_code(span) {
return true;
}
//If the span comes from a fake source_file, filter it.
!self.sess.source_map().lookup_char_pos(span.lo()).file.is_real_file()
}
}
macro_rules! filter {
($util: expr, $parent: expr) => {
if $util.filter_generated($parent) {
return None;
}
};
}

View File

@@ -1629,9 +1629,6 @@ options! {
saturating_float_casts: Option<bool> = (None, parse_opt_bool, [TRACKED],
"make float->int casts UB-free: numbers outside the integer type's range are clipped to \
the max/min integer respectively, and NaN is mapped to 0 (default: yes)"),
save_analysis: bool = (false, parse_bool, [UNTRACKED],
"write syntax and type analysis (in JSON format) information, in \
addition to normal output (default: no)"),
self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
parse_switch_with_opt_path, [UNTRACKED],
"run the self profiler and output the raw event data"),

View File

@@ -547,7 +547,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
response.value.certainty == Certainty::Yes
&& response.has_no_inference_or_external_constraints()
}) {
return Ok(response.clone());
return Ok(*response);
}
let certainty = candidates.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {

View File

@@ -1628,7 +1628,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Eventually I'll need to implement param-env-aware
// `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
let param_env = ty::ParamEnv::empty();
if self.can_sub(param_env, error, implication).is_ok() {
if self.can_sub(param_env, error, implication) {
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
return true;
}

View File

@@ -72,7 +72,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let impl_self_ty = impl_trait_ref.self_ty();
if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
self_match_impls.push((def_id, impl_substs));
if iter::zip(
@@ -261,7 +261,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
if let ty::Array(aty, len) = self_ty.kind() {
flags.push((sym::_Self, Some("[]".to_string())));
let len = len.kind().try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx));
let len = len.kind().try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
if let Some(n) = len {
flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));

View File

@@ -748,10 +748,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let real_ty = real_trait_pred.self_ty();
// We `erase_late_bound_regions` here because `make_subregion` does not handle
// `ReLateBound`, and we don't particularly care about the regions.
if self
.can_eq(obligation.param_env, self.tcx.erase_late_bound_regions(real_ty), arg_ty)
.is_err()
{
if !self.can_eq(
obligation.param_env,
self.tcx.erase_late_bound_regions(real_ty),
arg_ty,
) {
continue;
}
@@ -3690,7 +3691,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let Some((span, (assoc, ty))) = entry else { continue; };
if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
let Sorts(expected_found) = diff else { return false; };
self.can_eq(param_env, expected_found.found, ty).is_ok()
self.can_eq(param_env, expected_found.found, ty)
}) {
// FIXME: this doesn't quite work for `Iterator::collect`
// because we have `Vec<i32>` and `()`, but we'd want `i32`
@@ -3717,10 +3718,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
if self.can_eq(param_env, ty, *prev_ty).is_err() {
if !self.can_eq(param_env, ty, *prev_ty) {
if type_diffs.iter().any(|diff| {
let Sorts(expected_found) = diff else { return false; };
self.can_eq(param_env, expected_found.found, ty).is_ok()
self.can_eq(param_env, expected_found.found, ty)
}) {
primary_spans.push(span);
}
@@ -3868,7 +3869,7 @@ fn hint_missing_borrow<'tcx>(
let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
if infcx.can_eq(param_env, found_ty, expected_ty).is_ok() {
if infcx.can_eq(param_env, found_ty, expected_ty) {
// FIXME: This could handle more exotic cases like mutability mismatches too!
if found_refs.len() < expected_refs.len()
&& found_refs[..] == expected_refs[expected_refs.len() - found_refs.len()..]

View File

@@ -599,7 +599,7 @@ fn virtual_call_violation_for_method<'tcx>(
return false;
}
contains_illegal_self_type_reference(tcx, trait_def_id, pred.clone())
contains_illegal_self_type_reference(tcx, trait_def_id, pred)
}) {
return Some(MethodViolationCode::WhereClauseReferencesSelf);
}

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