Auto merge of #2639 - RalfJung:rustup, r=RalfJung

Rustup
This commit is contained in:
bors 2022-10-30 08:52:35 +00:00
commit 962bf63dbf
534 changed files with 8473 additions and 4512 deletions

View file

@ -1,3 +1,106 @@
Version 1.65.0 (2022-11-03)
==========================
Language
--------
- [Error on `as` casts of enums with `#[non_exhaustive]` variants](https://github.com/rust-lang/rust/pull/92744/)
- [Stabilize `let else`](https://github.com/rust-lang/rust/pull/93628/)
- [Stabilize generic associated types (GATs)](https://github.com/rust-lang/rust/pull/96709/)
- [Add lints `let_underscore_drop`, `let_underscore_lock`, and `let_underscore_must_use` from Clippy](https://github.com/rust-lang/rust/pull/97739/)
- [Stabilize `break`ing from arbitrary labeled blocks ("label-break-value")](https://github.com/rust-lang/rust/pull/99332/)
- [Uninitialized integers, floats, and raw pointers are now considered immediate UB](https://github.com/rust-lang/rust/pull/98919/).
Usage of `MaybeUninit` is the correct way to work with uninitialized memory.
- [Stabilize raw-dylib for Windows x86_64, aarch64, and thumbv7a](https://github.com/rust-lang/rust/pull/99916/)
- [Do not allow `Drop` impl on foreign ADTs](https://github.com/rust-lang/rust/pull/99576/)
Compiler
--------
- [Stabilize -Csplit-debuginfo on Linux](https://github.com/rust-lang/rust/pull/98051/)
- [Use niche-filling optimization even when multiple variants have data](https://github.com/rust-lang/rust/pull/94075/)
- [Associated type projections are now verified to be well-formed prior to resolving the underlying type](https://github.com/rust-lang/rust/pull/99217/#issuecomment-1209365630)
- [Stringify non-shorthand visibility correctly](https://github.com/rust-lang/rust/pull/100350/)
- [Normalize struct field types when unsizing](https://github.com/rust-lang/rust/pull/101831/)
- [Update to LLVM 15](https://github.com/rust-lang/rust/pull/99464/)
- [Fix aarch64 call abi to correctly zeroext when needed](https://github.com/rust-lang/rust/pull/97800/)
- [debuginfo: Generalize C++-like encoding for enums](https://github.com/rust-lang/rust/pull/98393/)
- [Add `special_module_name` lint](https://github.com/rust-lang/rust/pull/94467/)
- [Add support for generating unique profraw files by default when using `-C instrument-coverage`](https://github.com/rust-lang/rust/pull/100384/)
- [Allow dynamic linking for iOS/tvOS targets](https://github.com/rust-lang/rust/pull/100636/)
New targets:
- [Add armv4t-none-eabi as a tier 3 target](https://github.com/rust-lang/rust/pull/100244/)
- [Add powerpc64-unknown-openbsd and riscv64-unknown-openbsd as tier 3 targets](https://github.com/rust-lang/rust/pull/101025/)
- Refer to Rust's [platform support page][platform-support-doc] for more
information on Rust's tiered platform support.
Libraries
---------
- [Don't generate `PartialEq::ne` in derive(PartialEq)](https://github.com/rust-lang/rust/pull/98655/)
- [Windows RNG: Use `BCRYPT_RNG_ALG_HANDLE` by default](https://github.com/rust-lang/rust/pull/101325/)
- [Forbid mixing `System` with direct system allocator calls](https://github.com/rust-lang/rust/pull/101394/)
- [Document no support for writing to non-blocking stdio/stderr](https://github.com/rust-lang/rust/pull/101416/)
- [`std::layout::Layout` size must not overflow `isize::MAX` when rounded up to `align`](https://github.com/rust-lang/rust/pull/95295)
This also changes the safety conditions on `Layout::from_size_align_unchecked`.
Stabilized APIs
---------------
- [`std::backtrace::Backtrace`](https://doc.rust-lang.org/stable/std/backtrace/struct.Backtrace.html)
- [`Bound::as_ref`](https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.as_ref)
- [`std::io::read_to_string`](https://doc.rust-lang.org/stable/std/io/fn.read_to_string.html)
- [`<*const T>::cast_mut`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.cast_mut)
- [`<*mut T>::cast_const`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.cast_const)
These APIs are now stable in const contexts:
- [`<*const T>::offset_from`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from)
- [`<*mut T>::offset_from`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from)
Cargo
-----
- [Apply GitHub fast path even for partial hashes](https://github.com/rust-lang/cargo/pull/10807/)
- [Do not add home bin path to PATH if it's already there](https://github.com/rust-lang/cargo/pull/11023/)
- [Take priority into account within the pending queue](https://github.com/rust-lang/cargo/pull/11032/).
This slightly optimizes job scheduling by Cargo, with typically small improvements on larger crate graph builds.
Compatibility Notes
-------------------
- [`std::layout::Layout` size must not overflow `isize::MAX` when rounded up to `align`](https://github.com/rust-lang/rust/pull/95295).
This also changes the safety conditions on `Layout::from_size_align_unchecked`.
- [`PollFn` now only implements `Unpin` if the closure is `Unpin`](https://github.com/rust-lang/rust/pull/102737).
This is a possible breaking change if users were relying on the blanket unpin implementation.
See discussion on the PR for details of why this change was made.
- [Drop ExactSizeIterator impl from std::char::EscapeAscii](https://github.com/rust-lang/rust/pull/99880)
This is a backwards-incompatible change to the standard library's surface
area, but is unlikely to affect real world usage.
- [Do not consider a single repeated lifetime eligible for elision in the return type](https://github.com/rust-lang/rust/pull/103450)
This behavior was unintentionally changed in 1.64.0, and this release reverts that change by making this an error again.
- [Reenable disabled early syntax gates as future-incompatibility lints](https://github.com/rust-lang/rust/pull/99935/)
- [Update the minimum external LLVM to 13](https://github.com/rust-lang/rust/pull/100460/)
- [Don't duplicate file descriptors into stdio fds](https://github.com/rust-lang/rust/pull/101426/)
- [Sunset RLS](https://github.com/rust-lang/rust/pull/100863/)
- [Deny usage of `#![cfg_attr(..., crate_type = ...)]` to set the crate type](https://github.com/rust-lang/rust/pull/99784/)
This strengthens the forward compatibility lint deprecated_cfg_attr_crate_type_name to deny.
- [`llvm-has-rust-patches` allows setting the build system to treat the LLVM as having Rust-specific patches](https://github.com/rust-lang/rust/pull/101072)
This option may need to be set for distributions that are building Rust with a patched LLVM via `llvm-config`, not the built-in LLVM.
Internal Changes
----------------
These changes do not affect any public interfaces of Rust, but they represent
significant improvements to the performance or internals of rustc and related
tools.
- [Add `x.sh` and `x.ps1` shell scripts](https://github.com/rust-lang/rust/pull/99992/)
- [compiletest: use target cfg instead of hard-coded tables](https://github.com/rust-lang/rust/pull/100260/)
- [Use object instead of LLVM for reading bitcode from rlibs](https://github.com/rust-lang/rust/pull/98100/)
- [Enable MIR inlining for optimized compilations](https://github.com/rust-lang/rust/pull/91743)
This provides a 3-10% improvement in compiletimes for real world crates. See [perf results](https://perf.rust-lang.org/compare.html?start=aedf78e56b2279cc869962feac5153b6ba7001ed&end=0075bb4fad68e64b6d1be06bf2db366c30bc75e1&stat=instructions:u).
Version 1.64.0 (2022-09-22)
===========================

View file

@ -1112,24 +1112,6 @@ pub struct Expr {
}
impl Expr {
/// Returns `true` if this expression would be valid somewhere that expects a value;
/// for example, an `if` condition.
pub fn returns(&self) -> bool {
if let ExprKind::Block(ref block, _) = self.kind {
match block.stmts.last().map(|last_stmt| &last_stmt.kind) {
// Implicit return
Some(StmtKind::Expr(_)) => true,
// Last statement is an explicit return?
Some(StmtKind::Semi(expr)) => matches!(expr.kind, ExprKind::Ret(_)),
// This is a block that doesn't end in either an implicit or explicit return.
_ => false,
}
} else {
// This is not a block, it is a value.
true
}
}
/// Is this expr either `N`, or `{ N }`.
///
/// If this is not the case, name resolution does not resolve `N` when using

View file

@ -152,6 +152,12 @@ pub trait MutVisitor: Sized {
noop_visit_expr(e, self);
}
/// This method is a hack to workaround unstable of `stmt_expr_attributes`.
/// It can be removed once that feature is stabilized.
fn visit_method_receiver_expr(&mut self, ex: &mut P<Expr>) {
self.visit_expr(ex)
}
fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
noop_filter_map_expr(e, self)
}
@ -1301,7 +1307,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_ident(ident);
vis.visit_id(id);
visit_opt(args, |args| vis.visit_generic_args(args));
vis.visit_expr(receiver);
vis.visit_method_receiver_expr(receiver);
visit_exprs(exprs, vis);
vis.visit_span(span);
}
@ -1589,3 +1595,9 @@ impl DummyAstNode for Crate {
}
}
}
impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNodeWrapper<N, T> {
fn dummy() -> Self {
crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy())
}
}

View file

@ -140,6 +140,11 @@ pub trait Visitor<'ast>: Sized {
fn visit_expr(&mut self, ex: &'ast Expr) {
walk_expr(self, ex)
}
/// This method is a hack to workaround unstable of `stmt_expr_attributes`.
/// It can be removed once that feature is stabilized.
fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) {
self.visit_expr(ex)
}
fn visit_expr_post(&mut self, _ex: &'ast Expr) {}
fn visit_ty(&mut self, t: &'ast Ty) {
walk_ty(self, t)

View file

@ -112,19 +112,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
fn visit_nested_item(&mut self, item: ItemId) {
debug!("visit_nested_item: {:?}", item);
self.insert_nested(item.def_id.def_id);
self.insert_nested(item.owner_id.def_id);
}
fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
self.insert_nested(item_id.def_id.def_id);
self.insert_nested(item_id.owner_id.def_id);
}
fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
self.insert_nested(item_id.def_id.def_id);
self.insert_nested(item_id.owner_id.def_id);
}
fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) {
self.insert_nested(foreign_id.def_id.def_id);
self.insert_nested(foreign_id.owner_id.def_id);
}
fn visit_nested_body(&mut self, id: BodyId) {
@ -143,7 +143,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_item(&mut self, i: &'hir Item<'hir>) {
debug_assert_eq!(i.def_id, self.owner);
debug_assert_eq!(i.owner_id, self.owner);
self.with_parent(i.hir_id(), |this| {
if let ItemKind::Struct(ref struct_def, _) = i.kind {
// If this is a tuple or unit-like struct, register the constructor.
@ -157,7 +157,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
debug_assert_eq!(fi.def_id, self.owner);
debug_assert_eq!(fi.owner_id, self.owner);
self.with_parent(fi.hir_id(), |this| {
intravisit::walk_foreign_item(this, fi);
});
@ -176,7 +176,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
debug_assert_eq!(ti.def_id, self.owner);
debug_assert_eq!(ti.owner_id, self.owner);
self.with_parent(ti.hir_id(), |this| {
intravisit::walk_trait_item(this, ti);
});
@ -184,7 +184,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
debug_assert_eq!(ii.def_id, self.owner);
debug_assert_eq!(ii.owner_id, self.owner);
self.with_parent(ii.hir_id(), |this| {
intravisit::walk_impl_item(this, ii);
});

View file

@ -178,7 +178,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
let mut node_ids =
smallvec![hir::ItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
if let ItemKind::Use(ref use_tree) = &i.kind {
self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
}
@ -195,7 +195,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
UseTreeKind::Nested(ref nested_vec) => {
for &(ref nested, id) in nested_vec {
vec.push(hir::ItemId {
def_id: hir::OwnerId { def_id: self.local_def_id(id) },
owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
});
self.lower_item_id_use_tree(nested, id, vec);
}
@ -206,7 +206,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
{
vec.push(hir::ItemId {
def_id: hir::OwnerId { def_id: self.local_def_id(id) },
owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
});
}
}
@ -220,7 +220,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
let item = hir::Item {
def_id: hir_id.expect_owner(),
owner_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
kind,
vis_span,
@ -562,7 +562,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
let item = hir::Item {
def_id: hir::OwnerId { def_id: new_id },
owner_id: hir::OwnerId { def_id: new_id },
ident: this.lower_ident(ident),
kind,
vis_span,
@ -640,7 +640,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
let item = hir::Item {
def_id: hir::OwnerId { def_id: new_hir_id },
owner_id: hir::OwnerId { def_id: new_hir_id },
ident: this.lower_ident(ident),
kind,
vis_span,
@ -660,10 +660,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id);
let def_id = hir_id.expect_owner();
let owner_id = hir_id.expect_owner();
self.lower_attrs(hir_id, &i.attrs);
let item = hir::ForeignItem {
def_id,
owner_id,
ident: self.lower_ident(i.ident),
kind: match i.kind {
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
@ -702,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
hir::ForeignItemRef {
id: hir::ForeignItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
}
@ -845,7 +845,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_attrs(hir_id, &i.attrs);
let item = hir::TraitItem {
def_id: trait_item_def_id,
owner_id: trait_item_def_id,
ident: self.lower_ident(i.ident),
generics,
kind,
@ -864,7 +864,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
AssocItemKind::MacCall(..) => unimplemented!(),
};
let id = hir::TraitItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
hir::TraitItemRef {
id,
ident: self.lower_ident(i.ident),
@ -931,7 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs);
let item = hir::ImplItem {
def_id: hir_id.expect_owner(),
owner_id: hir_id.expect_owner(),
ident: self.lower_ident(i.ident),
generics,
kind,
@ -944,7 +944,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
hir::ImplItemRef {
id: hir::ImplItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
kind: match &i.kind {

View file

@ -1574,7 +1574,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
hir::TyKind::OpaqueDef(
hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } },
hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
lifetimes,
in_trait,
)
@ -1593,7 +1593,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_id);
let opaque_ty_item = hir::Item {
def_id: hir::OwnerId { def_id: opaque_ty_id },
owner_id: hir::OwnerId { def_id: opaque_ty_id },
ident: Ident::empty(),
kind: opaque_ty_item_kind,
vis_span: self.lower_span(span.shrink_to_lo()),
@ -2044,7 +2044,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// async fn, so the *type parameters* are inherited. It's
// only the lifetime parameters that we must supply.
let opaque_ty_ref = hir::TyKind::OpaqueDef(
hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } },
hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
generic_args,
in_trait,
);

View file

@ -1,7 +1,7 @@
use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
use rustc_ast::{PatKind, RangeEnd, VariantData};
use rustc_ast::{PatKind, RangeEnd};
use rustc_errors::{struct_span_err, Applicability, StashKey};
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
@ -116,46 +116,6 @@ impl<'a> PostExpansionVisitor<'a> {
}
}
fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
let has_fields = variants.iter().any(|variant| match variant.data {
VariantData::Tuple(..) | VariantData::Struct(..) => true,
VariantData::Unit(..) => false,
});
let discriminant_spans = variants
.iter()
.filter(|variant| match variant.data {
VariantData::Tuple(..) | VariantData::Struct(..) => false,
VariantData::Unit(..) => true,
})
.filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
.collect::<Vec<_>>();
if !discriminant_spans.is_empty() && has_fields {
let mut err = feature_err(
&self.sess.parse_sess,
sym::arbitrary_enum_discriminant,
discriminant_spans.clone(),
"custom discriminant values are not allowed in enums with tuple or struct variants",
);
for sp in discriminant_spans {
err.span_label(sp, "disallowed custom discriminant");
}
for variant in variants.iter() {
match &variant.data {
VariantData::Struct(..) => {
err.span_label(variant.span, "struct variant defined here");
}
VariantData::Tuple(..) => {
err.span_label(variant.span, "tuple variant defined here");
}
VariantData::Unit(..) => {}
}
}
err.emit();
}
}
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
fn check_impl_trait(&self, ty: &ast::Ty) {
struct ImplTraitVisitor<'a> {
@ -273,26 +233,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {
for variant in variants {
match (&variant.data, &variant.disr_expr) {
(ast::VariantData::Unit(..), _) => {}
(_, Some(disr_expr)) => gate_feature_post!(
&self,
arbitrary_enum_discriminant,
disr_expr.value.span,
"discriminants on non-unit variants are experimental"
),
_ => {}
}
}
let has_feature = self.features.arbitrary_enum_discriminant;
if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
self.maybe_report_invalid_custom_discriminants(&variants);
}
}
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => {
if let ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!(

View file

@ -92,7 +92,7 @@ pub struct OutlivesConstraint<'tcx> {
pub span: Span,
/// What caused this constraint?
pub category: ConstraintCategory,
pub category: ConstraintCategory<'tcx>,
/// Variance diagnostic information
pub variance_info: VarianceDiagInfo<'tcx>,

View file

@ -983,7 +983,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err: &mut Diagnostic,
location: Location,
issued_borrow: &BorrowData<'tcx>,
explanation: BorrowExplanation,
explanation: BorrowExplanation<'tcx>,
) {
let used_in_call = matches!(
explanation,
@ -1333,7 +1333,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow: &BorrowData<'tcx>,
drop_span: Span,
borrow_spans: UseSpans<'tcx>,
explanation: BorrowExplanation,
explanation: BorrowExplanation<'tcx>,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
debug!(
"report_local_value_does_not_live_long_enough(\
@ -1539,7 +1539,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
drop_span: Span,
borrow_spans: UseSpans<'tcx>,
proper_span: Span,
explanation: BorrowExplanation,
explanation: BorrowExplanation<'tcx>,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
explanation
@ -1653,7 +1653,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow: &BorrowData<'tcx>,
borrow_span: Span,
return_span: Span,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
opt_place_desc: Option<&String>,
) -> Option<DiagnosticBuilder<'cx, ErrorGuaranteed>> {
let return_kind = match category {
@ -1748,7 +1748,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
use_span: UseSpans<'tcx>,
var_span: Span,
fr_name: &RegionName,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
constraint_span: Span,
captured_var: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {

View file

@ -21,7 +21,7 @@ use crate::{
use super::{find_use, RegionName, UseSpans};
#[derive(Debug)]
pub(crate) enum BorrowExplanation {
pub(crate) enum BorrowExplanation<'tcx> {
UsedLater(LaterUseKind, Span, Option<Span>),
UsedLaterInLoop(LaterUseKind, Span, Option<Span>),
UsedLaterWhenDropped {
@ -30,7 +30,7 @@ pub(crate) enum BorrowExplanation {
should_note_order: bool,
},
MustBeValidFor {
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
from_closure: bool,
span: Span,
region_name: RegionName,
@ -49,7 +49,7 @@ pub(crate) enum LaterUseKind {
Other,
}
impl<'tcx> BorrowExplanation {
impl<'tcx> BorrowExplanation<'tcx> {
pub(crate) fn is_explained(&self) -> bool {
!matches!(self, BorrowExplanation::Unexplained)
}
@ -284,7 +284,7 @@ impl<'tcx> BorrowExplanation {
fn add_lifetime_bound_suggestion_to_diagnostic(
&self,
err: &mut Diagnostic,
category: &ConstraintCategory,
category: &ConstraintCategory<'tcx>,
span: Span,
region_name: &RegionName,
) {
@ -316,7 +316,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&self,
borrow_region: RegionVid,
outlived_region: RegionVid,
) -> (ConstraintCategory, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) {
) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) {
let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint(
borrow_region,
NllRegionVariableOrigin::FreeRegion,
@ -348,7 +348,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
location: Location,
borrow: &BorrowData<'tcx>,
kind_place: Option<(WriteKind, Place<'tcx>)>,
) -> BorrowExplanation {
) -> BorrowExplanation<'tcx> {
let regioncx = &self.regioncx;
let body: &Body<'_> = &self.body;
let tcx = self.infcx.tcx;

View file

@ -161,7 +161,7 @@ impl OutlivesSuggestionBuilder {
pub(crate) fn intermediate_suggestion(
&mut self,
mbcx: &MirBorrowckCtxt<'_, '_>,
errci: &ErrorConstraintInfo,
errci: &ErrorConstraintInfo<'_>,
diag: &mut Diagnostic,
) {
// Emit an intermediate note.

View file

@ -2,7 +2,6 @@
#![deny(rustc::diagnostic_outside_of_impl)]
//! Error reporting machinery for lifetime errors.
use either::Either;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
use rustc_hir::def_id::DefId;
@ -17,7 +16,7 @@ use rustc_infer::infer::{
NllRegionVariableOrigin, RelateParamBound,
};
use rustc_middle::hir::place::PlaceBase;
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint, TerminatorKind};
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::Region;
use rustc_middle::ty::TypeVisitor;
@ -40,7 +39,7 @@ use crate::{
MirBorrowckCtxt,
};
impl ConstraintDescription for ConstraintCategory {
impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
fn description(&self) -> &'static str {
// Must end with a space. Allows for empty names to be provided.
match self {
@ -116,7 +115,7 @@ pub(crate) enum RegionErrorKind<'tcx> {
/// Information about the various region constraints involved in a borrow checker error.
#[derive(Clone, Debug)]
pub struct ErrorConstraintInfo {
pub struct ErrorConstraintInfo<'tcx> {
// fr: outlived_fr
pub(super) fr: RegionVid,
pub(super) fr_is_local: bool,
@ -124,7 +123,7 @@ pub struct ErrorConstraintInfo {
pub(super) outlived_fr_is_local: bool,
// Category and span for best blame constraint
pub(super) category: ConstraintCategory,
pub(super) category: ConstraintCategory<'tcx>,
pub(super) span: Span,
}
@ -499,7 +498,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// ```
fn report_fnmut_error(
&self,
errci: &ErrorConstraintInfo,
errci: &ErrorConstraintInfo<'tcx>,
kind: ReturnConstraint,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
@ -572,7 +571,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn report_escaping_data_error(
&self,
errci: &ErrorConstraintInfo,
errci: &ErrorConstraintInfo<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let ErrorConstraintInfo { span, category, .. } = errci;
@ -676,7 +675,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// ```
fn report_general_error(
&self,
errci: &ErrorConstraintInfo,
errci: &ErrorConstraintInfo<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let ErrorConstraintInfo {
fr,
@ -789,7 +788,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
diag: &mut Diagnostic,
f: Region<'tcx>,
o: Region<'tcx>,
category: &ConstraintCategory,
category: &ConstraintCategory<'tcx>,
) {
if !o.is_static() {
return;
@ -797,12 +796,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let tcx = self.infcx.tcx;
let instance =
if let ConstraintCategory::CallArgument(location) = category
&& let Either::Right(term) = self.body.stmt_at(*location)
&& let TerminatorKind::Call { func, .. } = &term.kind
{
let func_ty = func.ty(self.body, tcx);
let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category {
let (fn_did, substs) = match func_ty.kind() {
ty::FnDef(fn_did, substs) => (fn_did, substs),
_ => return,

View file

@ -91,7 +91,7 @@ pub struct RegionInferenceContext<'tcx> {
/// Map closure bounds to a `Span` that should be used for error reporting.
closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
/// Map universe indexes to information on why we created it.
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
@ -267,7 +267,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
closure_bounds_mapping: FxHashMap<
Location,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
>,
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
type_tests: Vec<TypeTest<'tcx>>,
@ -1807,7 +1807,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn retrieve_closure_constraint_info(
&self,
constraint: OutlivesConstraint<'tcx>,
) -> Option<(ConstraintCategory, Span)> {
) -> Option<(ConstraintCategory<'tcx>, Span)> {
match constraint.locations {
Locations::All(_) => None,
Locations::Single(loc) => {
@ -1822,7 +1822,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fr1: RegionVid,
fr1_origin: NllRegionVariableOrigin,
fr2: RegionVid,
) -> (ConstraintCategory, ObligationCause<'tcx>) {
) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) {
let BlameConstraint { category, cause, .. } = self
.best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2))
.0;
@ -2362,7 +2362,7 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
#[derive(Clone, Debug)]
pub struct BlameConstraint<'tcx> {
pub category: ConstraintCategory,
pub category: ConstraintCategory<'tcx>,
pub from_closure: bool,
pub cause: ObligationCause<'tcx>,
pub variance_info: ty::VarianceDiagInfo<'tcx>,

View file

@ -263,13 +263,11 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies.
match infcx.register_hidden_type(
OpaqueTypeKey { def_id, substs: id_substs },
ObligationCause::misc(instantiated_ty.span, body_id),
param_env,
definition_ty,
origin,
) {
let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
match infcx
.at(&ObligationCause::misc(instantiated_ty.span, body_id), param_env)
.eq(opaque_ty, definition_ty)
{
Ok(infer_ok) => {
for obligation in infer_ok.obligations {
fulfillment_cx.register_predicate_obligation(&infcx, obligation);
@ -280,7 +278,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
.err_ctxt()
.report_mismatched_types(
&ObligationCause::misc(instantiated_ty.span, body_id),
self.tcx.mk_opaque(def_id.to_def_id(), id_substs),
opaque_ty,
definition_ty,
err,
)

View file

@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
pub(super) fn fully_perform_op<R: fmt::Debug, Op>(
&mut self,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
op: Op,
) -> Fallible<R>
where
@ -85,7 +85,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
&mut self,
trait_ref: ty::TraitRef<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
self.prove_predicate(
ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
@ -124,7 +124,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
&mut self,
predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
for predicate in predicates {
let predicate = predicate.to_predicate(self.tcx());
@ -139,7 +139,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
&mut self,
predicate: ty::Predicate<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
let param_env = self.param_env;
self.fully_perform_op(
@ -164,7 +164,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
&mut self,
value: T,
location: impl NormalizeLocation,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> T
where
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,

View file

@ -37,7 +37,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
span: Span,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
}
@ -50,7 +50,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
span: Span,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
) -> Self {
Self {
@ -175,7 +175,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
&mut self,
sup: ty::RegionVid,
sub: ty::RegionVid,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
let category = match self.category {
ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category,
@ -203,7 +203,7 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'
_origin: SubregionOrigin<'tcx>,
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
constraint_category: ConstraintCategory,
constraint_category: ConstraintCategory<'tcx>,
) {
let b = self.to_region_vid(b);
let a = self.to_region_vid(a);

View file

@ -942,7 +942,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
pub(crate) closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
@ -1133,7 +1133,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn push_region_constraints(
&mut self,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
data: &QueryRegionConstraints<'tcx>,
) {
debug!("constraints generated: {:#?}", data);
@ -1158,7 +1158,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
sub: Ty<'tcx>,
sup: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
// Use this order of parameters because the sup type is usually the
// "expected" type in diagnostics.
@ -1171,7 +1171,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
expected: Ty<'tcx>,
found: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
}
@ -1183,7 +1183,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
v: ty::Variance,
user_ty: &UserTypeProjection,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
@ -1618,12 +1618,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
}
let func_ty = if let TerminatorKind::Call { func, .. } = &term.kind {
Some(func.ty(body, self.infcx.tcx))
} else {
None
};
debug!(?func_ty);
for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
let op_arg_ty = op_arg.ty(body, self.tcx());
let op_arg_ty = self.normalize(op_arg_ty, term_location);
let category = if from_hir_call {
ConstraintCategory::CallArgument(term_location)
ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
} else {
ConstraintCategory::Boring
};
@ -1776,7 +1783,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `Sized` bound in no way depends on precise regions, so this
// shouldn't affect `is_sized`.
let erased_ty = tcx.erase_regions(ty);
if !erased_ty.is_sized(tcx.at(span), self.param_env) {
if !erased_ty.is_sized(tcx, self.param_env) {
// in current MIR construction, all non-control-flow rvalue
// expressions evaluate through `as_temp` or `into` a return
// slot or local, so to find all unsized rvalues it is enough

View file

@ -1,6 +1,6 @@
use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::TypeRelation;
@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
v: ty::Variance,
b: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
TypeRelating::new(
self.infcx,
@ -45,7 +45,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
a: ty::SubstsRef<'tcx>,
b: ty::SubstsRef<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
TypeRelating::new(
self.infcx,
@ -64,7 +64,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
locations: Locations,
/// What category do we assign the resulting `'a: 'b` relationships?
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
/// Information so that error reporting knows what types we are relating
/// when reporting a bound region error.
@ -75,7 +75,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
fn new(
type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
universe_info: UniverseInfo<'tcx>,
) -> Self {
Self { type_checker, locations, category, universe_info }
@ -155,27 +155,16 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
true
}
fn register_opaque_type(
fn register_opaque_type_obligations(
&mut self,
a: Ty<'tcx>,
b: Ty<'tcx>,
a_is_expected: bool,
obligations: PredicateObligations<'tcx>,
) -> Result<(), TypeError<'tcx>> {
let param_env = self.param_env();
let span = self.span();
let def_id = self.type_checker.body.source.def_id().expect_local();
let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id);
let cause = ObligationCause::misc(span, body_id);
self.type_checker
.fully_perform_op(
self.locations,
self.category,
InstantiateOpaqueType {
obligations: self
.type_checker
.infcx
.handle_opaque_type(a, b, a_is_expected, &cause, param_env)?
.obligations,
obligations,
// These fields are filled in during execution of the operation
base_universe: None,
region_constraints: None,

View file

@ -210,8 +210,15 @@ impl CfgEval<'_, '_> {
}
impl MutVisitor for CfgEval<'_, '_> {
#[instrument(level = "trace", skip(self))]
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
self.cfg.configure_expr(expr);
self.cfg.configure_expr(expr, false);
mut_visit::noop_visit_expr(expr, self);
}
#[instrument(level = "trace", skip(self))]
fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
self.cfg.configure_expr(expr, true);
mut_visit::noop_visit_expr(expr, self);
}

View file

@ -770,11 +770,7 @@ fn codegen_stmt<'tcx>(
lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
}
Rvalue::NullaryOp(null_op, ty) => {
assert!(
lval.layout()
.ty
.is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all())
);
assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all()));
let layout = fx.layout_of(fx.monomorphize(ty));
let val = match null_op {
NullOp::SizeOf => layout.size.bytes(),

View file

@ -5,7 +5,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
};
use rustc_span::DUMMY_SP;
use cranelift_module::*;
@ -291,7 +290,7 @@ fn data_id_for_static(
let is_mutable = if tcx.is_mutable_static(def_id) {
true
} else {
!ty.is_freeze(tcx.at(DUMMY_SP), ParamEnv::reveal_all())
!ty.is_freeze(tcx, ParamEnv::reveal_all())
};
let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();

View file

@ -5,7 +5,6 @@ use crate::common::TypeKind;
use crate::mir::place::PlaceRef;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, Ty};
use rustc_span::DUMMY_SP;
use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
use rustc_target::abi::{AddressSpace, Integer};
@ -75,16 +74,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
}
fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all())
ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all())
}
fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
ty.is_freeze(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all())
ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all())
}
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
let param_env = ty::ParamEnv::reveal_all();
if ty.is_sized(self.tcx().at(DUMMY_SP), param_env) {
if ty.is_sized(self.tcx(), param_env) {
return false;
}

View file

@ -25,10 +25,12 @@ pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
/// report whether said intrinsic has a `rustc_const_{un,}stable` attribute. Otherwise, return
/// `Constness::NotConst`.
fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
match tcx.hir().get(hir_id) {
hir::Node::Ctor(_) => hir::Constness::Const,
let def_id = def_id.expect_local();
let node = tcx.hir().get_by_def_id(def_id);
match node {
hir::Node::Ctor(_) => hir::Constness::Const,
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
// foreign items cannot be evaluated at compile-time.
@ -39,62 +41,20 @@ fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
};
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
}
_ => {
if let Some(fn_kind) = node.fn_kind() {
if fn_kind.constness() == hir::Constness::Const {
return hir::Constness::Const;
}
hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
if tcx.is_const_default_method(def_id) =>
{
hir::Constness::Const
}
hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. })
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. })
| hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. })
| hir::Node::AnonConst(_)
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
| hir::Node::ImplItem(hir::ImplItem {
kind:
hir::ImplItemKind::Fn(
hir::FnSig {
header: hir::FnHeader { constness: hir::Constness::Const, .. },
..
},
..,
),
..
}) => hir::Constness::Const,
hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..),
..
}) => {
let parent_hir_id = tcx.hir().get_parent_node(hir_id);
match tcx.hir().get(parent_hir_id) {
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
..
}) => *constness,
_ => span_bug!(
tcx.def_span(parent_hir_id.owner),
"impl item's parent node is not an impl",
),
// If the function itself is not annotated with `const`, it may still be a `const fn`
// if it resides in a const trait impl.
let is_const = is_parent_const_impl_raw(tcx, def_id);
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
} else {
hir::Constness::NotConst
}
}
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..),
..
})
| hir::Node::TraitItem(hir::TraitItem {
kind:
hir::TraitItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..),
..
})
| hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
..
}) => *constness,
_ => hir::Constness::NotConst,
}
}

View file

@ -2,10 +2,10 @@ use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::ty::{self, Ty, TyCtxt};
use std::borrow::Borrow;
use std::collections::hash_map::Entry;
use std::hash::Hash;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::fx::IndexEntry;
use std::fmt;
use rustc_ast::Mutability;
@ -107,18 +107,18 @@ impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
}
}
impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
#[inline(always)]
fn contains_key<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> bool
where
K: Borrow<Q>,
{
FxHashMap::contains_key(self, k)
FxIndexMap::contains_key(self, k)
}
#[inline(always)]
fn insert(&mut self, k: K, v: V) -> Option<V> {
FxHashMap::insert(self, k, v)
FxIndexMap::insert(self, k, v)
}
#[inline(always)]
@ -126,7 +126,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
where
K: Borrow<Q>,
{
FxHashMap::remove(self, k)
FxIndexMap::remove(self, k)
}
#[inline(always)]
@ -148,8 +148,8 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
#[inline(always)]
fn get_mut_or<E>(&mut self, k: K, vacant: impl FnOnce() -> Result<V, E>) -> Result<&mut V, E> {
match self.entry(k) {
Entry::Occupied(e) => Ok(e.into_mut()),
Entry::Vacant(e) => {
IndexEntry::Occupied(e) => Ok(e.into_mut()),
IndexEntry::Vacant(e) => {
let v = vacant()?;
Ok(e.insert(v))
}

View file

@ -212,7 +212,7 @@ fn create_pointee_place<'tcx>(
) -> MPlaceTy<'tcx> {
let tcx = ecx.tcx.tcx;
if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) {
if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty()) {
// We need to create `Allocation`s for custom DSTs
let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx);
@ -398,7 +398,7 @@ fn valtree_into_mplace<'tcx>(
let mut place_inner = match ty.kind() {
ty::Str | ty::Slice(_) => ecx.mplace_index(&place, i as u64).unwrap(),
_ if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty())
_ if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty())
&& i == branches.len() - 1 =>
{
// Note: For custom DSTs we need to manually process the last unsized field.

View file

@ -138,23 +138,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(())
}
/// Handles 'IntToInt' and 'IntToFloat' casts.
pub fn int_to_int_or_float(
&mut self,
&self,
src: &ImmTy<'tcx, M::Provenance>,
cast_ty: Ty<'tcx>,
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
if (src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool())
&& (cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char())
{
let scalar = src.to_scalar();
Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
} else {
bug!("Unexpected cast from type {:?}", src.layout.ty)
}
assert!(src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool());
assert!(cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char());
Ok(self.cast_from_int_like(src.to_scalar(), src.layout, cast_ty)?.into())
}
/// Handles 'FloatToFloat' and 'FloatToInt' casts.
pub fn float_to_float_or_int(
&mut self,
&self,
src: &ImmTy<'tcx, M::Provenance>,
cast_ty: Ty<'tcx>,
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
@ -176,35 +174,33 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Handles 'FnPtrToPtr' and 'PtrToPtr' casts.
pub fn ptr_to_ptr(
&mut self,
&self,
src: &ImmTy<'tcx, M::Provenance>,
cast_ty: Ty<'tcx>,
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
assert!(src.layout.ty.is_any_ptr());
assert!(cast_ty.is_unsafe_ptr());
// Handle casting any ptr to raw ptr (might be a fat ptr).
if src.layout.ty.is_any_ptr() && cast_ty.is_unsafe_ptr() {
let dest_layout = self.layout_of(cast_ty)?;
if dest_layout.size == src.layout.size {
// Thin or fat pointer that just hast the ptr kind of target type changed.
return Ok(**src);
} else {
// Casting the metadata away from a fat ptr.
assert_eq!(src.layout.size, 2 * self.pointer_size());
assert_eq!(dest_layout.size, self.pointer_size());
assert!(src.layout.ty.is_unsafe_ptr());
return match **src {
Immediate::ScalarPair(data, _) => Ok(data.into()),
Immediate::Scalar(..) => span_bug!(
self.cur_span(),
"{:?} input to a fat-to-thin cast ({:?} -> {:?})",
*src,
src.layout.ty,
cast_ty
),
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
};
}
let dest_layout = self.layout_of(cast_ty)?;
if dest_layout.size == src.layout.size {
// Thin or fat pointer that just hast the ptr kind of target type changed.
return Ok(**src);
} else {
bug!("Can't cast 'Ptr' or 'FnPtr' into {:?}", cast_ty);
// Casting the metadata away from a fat ptr.
assert_eq!(src.layout.size, 2 * self.pointer_size());
assert_eq!(dest_layout.size, self.pointer_size());
assert!(src.layout.ty.is_unsafe_ptr());
return match **src {
Immediate::ScalarPair(data, _) => Ok(data.into()),
Immediate::Scalar(..) => span_bug!(
self.cur_span(),
"{:?} input to a fat-to-thin cast ({:?} -> {:?})",
*src,
src.layout.ty,
cast_ty
),
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
};
}
}
@ -226,7 +222,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
pub fn pointer_from_exposed_address_cast(
&mut self,
&self,
src: &ImmTy<'tcx, M::Provenance>,
cast_ty: Ty<'tcx>,
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
@ -243,6 +239,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(Scalar::from_maybe_pointer(ptr, self).into())
}
/// Low-level cast helper function. This works directly on scalars and can take 'int-like' input
/// type (basically everything with a scalar layout) to int/float/char types.
pub fn cast_from_int_like(
&self,
scalar: Scalar<M::Provenance>, // input value (there is no ScalarTy so we separate data+layout)
@ -282,6 +280,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
})
}
/// Low-level cast helper function. Converts an apfloat `f` into int or float types.
fn cast_from_float<F>(&self, f: F, dest_ty: Ty<'tcx>) -> Scalar<M::Provenance>
where
F: Float + Into<Scalar<M::Provenance>> + FloatConvert<Single> + FloatConvert<Double>,

View file

@ -468,7 +468,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
#[inline]
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
ty.is_freeze(self.tcx, self.param_env)
ty.is_freeze(*self.tcx, self.param_env)
}
pub fn load_mir(

View file

@ -15,7 +15,7 @@
//! that contains allocations whose mutability we cannot identify.)
use super::validity::RefTracking;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_middle::mir::interpret::InterpResult;
@ -37,7 +37,7 @@ pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
ExtraFnVal = !,
FrameExtra = (),
AllocExtra = (),
MemoryMap = FxHashMap<AllocId, (MemoryKind<T>, Allocation)>,
MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
>;
struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> {
@ -47,7 +47,7 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_ev
ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, InternMode)>,
/// A list of all encountered allocations. After type-based interning, we traverse this list to
/// also intern allocations that are only referenced by a raw pointer or inside a union.
leftover_allocations: &'rt mut FxHashSet<AllocId>,
leftover_allocations: &'rt mut FxIndexSet<AllocId>,
/// The root kind of the value that we're looking at. This field is never mutated for a
/// particular allocation. It is primarily used to make as many allocations as possible
/// read-only so LLVM can place them in const memory.
@ -79,7 +79,7 @@ struct IsStaticOrFn;
/// to account for (e.g. for vtables).
fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>(
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
leftover_allocations: &'rt mut FxHashSet<AllocId>,
leftover_allocations: &'rt mut FxIndexSet<AllocId>,
alloc_id: AllocId,
mode: InternMode,
ty: Option<Ty<'tcx>>,
@ -114,7 +114,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
if let InternMode::Static(mutability) = mode {
// For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
// no interior mutability.
let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx, ecx.param_env));
let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env));
// For statics, allocation mutability is the combination of place mutability and
// type mutability.
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
@ -355,7 +355,7 @@ pub fn intern_const_alloc_recursive<
// `leftover_allocations` collects *all* allocations we see, because some might not
// be available in a typed way. They get interned at the end.
let mut ref_tracking = RefTracking::empty();
let leftover_allocations = &mut FxHashSet::default();
let leftover_allocations = &mut FxIndexSet::default();
// start with the outermost allocation
intern_shallow(

View file

@ -4,7 +4,7 @@ use rustc_hir::definitions::DisambiguatedDefPathData;
use rustc_middle::mir::interpret::{Allocation, ConstAllocation};
use rustc_middle::ty::{
self,
print::{PrettyPrinter, Print, Printer},
print::{with_no_verbose_constants, PrettyPrinter, Print, Printer},
subst::{GenericArg, GenericArgKind},
Ty, TyCtxt,
};
@ -190,7 +190,9 @@ impl Write for AbsolutePathPrinter<'_> {
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
let path = with_no_verbose_constants!(
AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path
);
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
tcx.intern_const_alloc(alloc)
}

View file

@ -426,7 +426,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
type ExtraFnVal = !;
type MemoryMap =
rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>;
rustc_data_structures::fx::FxIndexMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>;
const GLOBAL_KIND: Option<Self::MemoryKind> = None; // no copying of globals from `tcx` to machine memory
type AllocExtra = ();

View file

@ -554,6 +554,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
val: &mir::ConstantKind<'tcx>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
// FIXME(const_prop): normalization needed b/c const prop lint in
// `mir_drops_elaborated_and_const_checked`, which happens before
// optimized MIR. Only after optimizing the MIR can we guarantee
// that the `RevealAll` pass has happened and that the body's consts
// are normalized, so any call to resolve before that needs to be
// manually normalized.
let val = self.tcx.normalize_erasing_regions(self.param_env, *val);
match val {
mir::ConstantKind::Ty(ct) => {
match ct.kind() {
@ -585,7 +592,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}
}
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout),
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout),
mir::ConstantKind::Unevaluated(uv, _) => {
let instance = self.resolve(uv.def, uv.substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())

View file

@ -15,7 +15,6 @@ use rustc_middle::mir::interpret::InterpError;
use rustc_middle::ty;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::DUMMY_SP;
use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange};
use std::hash::Hash;
@ -726,7 +725,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
) -> InterpResult<'tcx> {
// Special check preventing `UnsafeCell` inside unions in the inner part of constants.
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. })) {
if !op.layout.ty.is_freeze(self.ecx.tcx.at(DUMMY_SP), self.ecx.param_env) {
if !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" });
}
}

View file

@ -22,7 +22,6 @@ Rust MIR: a lowered representation of Rust.
#![feature(yeet_expr)]
#![feature(is_some_and)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#[macro_use]
extern crate tracing;

View file

@ -8,7 +8,6 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::{
self, ImplSource, Obligation, ObligationCause, SelectionContext,
};
@ -92,7 +91,7 @@ impl Qualif for HasMutInterior {
}
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
!ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env)
!ty.is_freeze(cx.tcx, cx.param_env)
}
fn in_adt_inherently<'tcx>(

View file

@ -8,7 +8,6 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementK
use rustc_mir_dataflow::fmt::DebugWithContext;
use rustc_mir_dataflow::JoinSemiLattice;
use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces};
use rustc_span::DUMMY_SP;
use std::fmt;
use std::marker::PhantomData;
@ -120,10 +119,7 @@ where
///
/// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
!place
.ty(self.ccx.body, self.ccx.tcx)
.ty
.is_freeze(self.ccx.tcx.at(DUMMY_SP), self.ccx.param_env)
!place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.param_env)
}
}

View file

@ -41,10 +41,6 @@ pub struct PromoteTemps<'tcx> {
}
impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
fn phase_change(&self) -> Option<MirPhase> {
Some(MirPhase::Analysis(AnalysisPhase::Initial))
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// There's not really any point in promoting errorful MIR.
//

View file

@ -235,9 +235,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// `Operand::Copy` is only supposed to be used with `Copy` types.
if let Operand::Copy(place) = operand {
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
let span = self.body.source_info(location).span;
if !ty.is_copy_modulo_regions(self.tcx.at(span), self.param_env) {
if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
}
}

View file

@ -22,6 +22,7 @@
#![feature(new_uninit)]
#![feature(once_cell)]
#![feature(rustc_attrs)]
#![feature(negative_impls)]
#![feature(test)]
#![feature(thread_id_value)]
#![feature(vec_into_raw_parts)]
@ -86,6 +87,7 @@ pub mod steal;
pub mod tagged_ptr;
pub mod temp_dir;
pub mod unhash;
pub mod unord;
pub use ena::undo_log;
pub use ena::unify;

View file

@ -0,0 +1,382 @@
//! This module contains collection types that don't expose their internal
//! ordering. This is a useful property for deterministic computations, such
//! as required by the query system.
use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::SmallVec;
use std::{
borrow::Borrow,
hash::Hash,
iter::{Product, Sum},
};
use crate::{
fingerprint::Fingerprint,
stable_hasher::{HashStable, StableHasher, ToStableHashKey},
};
/// `UnordItems` is the order-less version of `Iterator`. It only contains methods
/// that don't (easily) expose an ordering of the underlying items.
///
/// Most methods take an `Fn` where the `Iterator`-version takes an `FnMut`. This
/// is to reduce the risk of accidentally leaking the internal order via the closure
/// environment. Otherwise one could easily do something like
///
/// ```rust,ignore (pseudo code)
/// let mut ordered = vec![];
/// unordered_items.all(|x| ordered.push(x));
/// ```
///
/// It's still possible to do the same thing with an `Fn` by using interior mutability,
/// but the chance of doing it accidentally is reduced.
pub struct UnordItems<T, I: Iterator<Item = T>>(I);
impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
#[inline]
pub fn map<U, F: Fn(T) -> U>(self, f: F) -> UnordItems<U, impl Iterator<Item = U>> {
UnordItems(self.0.map(f))
}
#[inline]
pub fn all<U, F: Fn(T) -> bool>(mut self, f: F) -> bool {
self.0.all(f)
}
#[inline]
pub fn any<U, F: Fn(T) -> bool>(mut self, f: F) -> bool {
self.0.any(f)
}
#[inline]
pub fn filter<U, F: Fn(&T) -> bool>(self, f: F) -> UnordItems<T, impl Iterator<Item = T>> {
UnordItems(self.0.filter(f))
}
#[inline]
pub fn filter_map<U, F: Fn(T) -> Option<U>>(
self,
f: F,
) -> UnordItems<U, impl Iterator<Item = U>> {
UnordItems(self.0.filter_map(f))
}
#[inline]
pub fn max(self) -> Option<T>
where
T: Ord,
{
self.0.max()
}
#[inline]
pub fn min(self) -> Option<T>
where
T: Ord,
{
self.0.min()
}
#[inline]
pub fn sum<S>(self) -> S
where
S: Sum<T>,
{
self.0.sum()
}
#[inline]
pub fn product<S>(self) -> S
where
S: Product<T>,
{
self.0.product()
}
#[inline]
pub fn count(self) -> usize {
self.0.count()
}
}
impl<'a, T: Clone + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
#[inline]
pub fn cloned(self) -> UnordItems<T, impl Iterator<Item = T>> {
UnordItems(self.0.cloned())
}
}
impl<'a, T: Copy + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
#[inline]
pub fn copied(self) -> UnordItems<T, impl Iterator<Item = T>> {
UnordItems(self.0.copied())
}
}
impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
pub fn into_sorted<HCX>(self, hcx: &HCX) -> Vec<T>
where
T: ToStableHashKey<HCX>,
{
let mut items: Vec<T> = self.0.collect();
items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
items
}
pub fn into_sorted_small_vec<HCX, const LEN: usize>(self, hcx: &HCX) -> SmallVec<[T; LEN]>
where
T: ToStableHashKey<HCX>,
{
let mut items: SmallVec<[T; LEN]> = self.0.collect();
items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
items
}
}
/// This is a set collection type that tries very hard to not expose
/// any internal iteration. This is a useful property when trying to
/// uphold the determinism invariants imposed by the query system.
///
/// This collection type is a good choice for set-like collections the
/// keys of which don't have a semantic ordering.
///
/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
/// for more information.
#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
pub struct UnordSet<V: Eq + Hash> {
inner: FxHashSet<V>,
}
impl<V: Eq + Hash> Default for UnordSet<V> {
fn default() -> Self {
Self { inner: FxHashSet::default() }
}
}
impl<V: Eq + Hash> UnordSet<V> {
#[inline]
pub fn new() -> Self {
Self { inner: Default::default() }
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn insert(&mut self, v: V) -> bool {
self.inner.insert(v)
}
#[inline]
pub fn contains<Q: ?Sized>(&self, v: &Q) -> bool
where
V: Borrow<Q>,
Q: Hash + Eq,
{
self.inner.contains(v)
}
#[inline]
pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator<Item = &'a V>> {
UnordItems(self.inner.iter())
}
#[inline]
pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
UnordItems(self.inner.into_iter())
}
// We can safely extend this UnordSet from a set of unordered values because that
// won't expose the internal ordering anywhere.
#[inline]
pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
self.inner.extend(items.0)
}
}
impl<V: Hash + Eq> Extend<V> for UnordSet<V> {
fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
self.inner.extend(iter)
}
}
impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> {
#[inline]
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
hash_iter_order_independent(self.inner.iter(), hcx, hasher);
}
}
/// This is a map collection type that tries very hard to not expose
/// any internal iteration. This is a useful property when trying to
/// uphold the determinism invariants imposed by the query system.
///
/// This collection type is a good choice for map-like collections the
/// keys of which don't have a semantic ordering.
///
/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
/// for more information.
#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
pub struct UnordMap<K: Eq + Hash, V> {
inner: FxHashMap<K, V>,
}
impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
fn default() -> Self {
Self { inner: FxHashMap::default() }
}
}
impl<K: Hash + Eq, V> Extend<(K, V)> for UnordMap<K, V> {
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
self.inner.extend(iter)
}
}
impl<K: Eq + Hash, V> UnordMap<K, V> {
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
self.inner.insert(k, v)
}
#[inline]
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.inner.contains_key(k)
}
#[inline]
pub fn items<'a>(&'a self) -> UnordItems<(&'a K, &'a V), impl Iterator<Item = (&'a K, &'a V)>> {
UnordItems(self.inner.iter())
}
#[inline]
pub fn into_items(self) -> UnordItems<(K, V), impl Iterator<Item = (K, V)>> {
UnordItems(self.inner.into_iter())
}
// We can safely extend this UnordMap from a set of unordered values because that
// won't expose the internal ordering anywhere.
#[inline]
pub fn extend<I: Iterator<Item = (K, V)>>(&mut self, items: UnordItems<(K, V), I>) {
self.inner.extend(items.0)
}
}
impl<HCX, K: Hash + Eq + HashStable<HCX>, V: HashStable<HCX>> HashStable<HCX> for UnordMap<K, V> {
#[inline]
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
hash_iter_order_independent(self.inner.iter(), hcx, hasher);
}
}
/// This is a collection type that tries very hard to not expose
/// any internal iteration. This is a useful property when trying to
/// uphold the determinism invariants imposed by the query system.
///
/// This collection type is a good choice for collections the
/// keys of which don't have a semantic ordering and don't implement
/// `Hash` or `Eq`.
///
/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
/// for more information.
#[derive(Default, Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
pub struct UnordBag<V> {
inner: Vec<V>,
}
impl<V> UnordBag<V> {
#[inline]
pub fn new() -> Self {
Self { inner: Default::default() }
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn push(&mut self, v: V) {
self.inner.push(v);
}
#[inline]
pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator<Item = &'a V>> {
UnordItems(self.inner.iter())
}
#[inline]
pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
UnordItems(self.inner.into_iter())
}
// We can safely extend this UnordSet from a set of unordered values because that
// won't expose the internal ordering anywhere.
#[inline]
pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
self.inner.extend(items.0)
}
}
impl<T> Extend<T> for UnordBag<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.inner.extend(iter)
}
}
impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordBag<V> {
#[inline]
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
hash_iter_order_independent(self.inner.iter(), hcx, hasher);
}
}
fn hash_iter_order_independent<
HCX,
T: HashStable<HCX>,
I: Iterator<Item = T> + ExactSizeIterator,
>(
mut it: I,
hcx: &mut HCX,
hasher: &mut StableHasher,
) {
let len = it.len();
len.hash_stable(hcx, hasher);
match len {
0 => {
// We're done
}
1 => {
// No need to instantiate a hasher
it.next().unwrap().hash_stable(hcx, hasher);
}
_ => {
let mut accumulator = Fingerprint::ZERO;
for item in it {
let mut item_hasher = StableHasher::new();
item.hash_stable(hcx, &mut item_hasher);
let item_fingerprint: Fingerprint = item_hasher.finish();
accumulator = accumulator.combine_commutative(item_fingerprint);
}
accumulator.hash_stable(hcx, hasher);
}
}
}
// Do not implement IntoIterator for the collections in this module.
// They only exist to hide iteration order in the first place.
impl<T> !IntoIterator for UnordBag<T> {}
impl<V> !IntoIterator for UnordSet<V> {}
impl<K, V> !IntoIterator for UnordMap<K, V> {}
impl<T, I> !IntoIterator for UnordItems<T, I> {}

View file

@ -427,18 +427,6 @@ fn run_compiler(
})
}
#[cfg(unix)]
pub fn set_sigpipe_handler() {
unsafe {
// Set the SIGPIPE signal handler, so that an EPIPE
// will cause rustc to terminate, as expected.
assert_ne!(libc::signal(libc::SIGPIPE, libc::SIG_DFL), libc::SIG_ERR);
}
}
#[cfg(windows)]
pub fn set_sigpipe_handler() {}
// Extract output directory and file from matches.
fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));

View file

@ -3,8 +3,6 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`.
Erroneous code example:
```compile_fail,E0732
#![feature(arbitrary_enum_discriminant)]
enum Enum { // error!
Unit = 1,
Tuple() = 2,
@ -20,8 +18,6 @@ is a well-defined way to extract a variant's discriminant from a value;
for instance:
```
#![feature(arbitrary_enum_discriminant)]
#[repr(u8)]
enum Enum {
Unit = 3,

View file

@ -93,7 +93,7 @@ hir_analysis_expected_default_return_type = expected `()` because of default ret
hir_analysis_expected_return_type = expected `{$expected}` because of return type
hir_analysis_unconstrained_opaque_type = unconstrained opaque type
.note = `{$name}` must be used in combination with a concrete type within the same module
.note = `{$name}` must be used in combination with a concrete type within the same {$what}
hir_analysis_missing_type_params =
the type {$parameterCount ->
@ -137,3 +137,16 @@ hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(l
hir_analysis_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
hir_analysis_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
hir_analysis_const_impl_for_non_const_trait =
const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
.suggestion = mark `{$trait_name}` as const
.note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
.adding = adding a non-const method body in the future would be a breaking change
hir_analysis_const_bound_for_non_const_trait =
~const can only be applied to `#[const_trait]` traits
hir_analysis_self_in_impl_self =
`Self` is not valid in the self type of an impl block
.note = replace `Self` with a different type

View file

@ -690,6 +690,24 @@ impl Diagnostic {
msg: impl Into<SubdiagnosticMessage>,
suggestions: impl Iterator<Item = String>,
applicability: Applicability,
) -> &mut Self {
self.span_suggestions_with_style(
sp,
msg,
suggestions,
applicability,
SuggestionStyle::ShowCode,
)
}
/// [`Diagnostic::span_suggestions()`] but you can set the [`SuggestionStyle`].
pub fn span_suggestions_with_style(
&mut self,
sp: Span,
msg: impl Into<SubdiagnosticMessage>,
suggestions: impl Iterator<Item = String>,
applicability: Applicability,
style: SuggestionStyle,
) -> &mut Self {
let mut suggestions: Vec<_> = suggestions.collect();
suggestions.sort();
@ -706,14 +724,15 @@ impl Diagnostic {
self.push_suggestion(CodeSuggestion {
substitutions,
msg: self.subdiagnostic_message_to_diagnostic_message(msg),
style: SuggestionStyle::ShowCode,
style,
applicability,
});
self
}
/// Prints out a message with multiple suggested edits of the code.
/// See also [`Diagnostic::span_suggestion()`].
/// Prints out a message with multiple suggested edits of the code, where each edit consists of
/// multiple parts.
/// See also [`Diagnostic::multipart_suggestion()`].
pub fn multipart_suggestions(
&mut self,
msg: impl Into<SubdiagnosticMessage>,
@ -745,6 +764,7 @@ impl Diagnostic {
});
self
}
/// Prints out a message with a suggested edit of the code. If the suggestion is presented
/// inline, it will only show the message and not the suggestion.
///

View file

@ -469,6 +469,7 @@ impl<'a> StripUnconfigured<'a> {
}
/// If attributes are not allowed on expressions, emit an error for `attr`
#[instrument(level = "trace", skip(self))]
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
if !self.features.map_or(true, |features| features.stmt_expr_attributes) {
let mut err = feature_err(
@ -486,9 +487,12 @@ impl<'a> StripUnconfigured<'a> {
}
}
pub fn configure_expr(&self, expr: &mut P<ast::Expr>) {
for attr in expr.attrs.iter() {
self.maybe_emit_expr_attr_err(attr);
#[instrument(level = "trace", skip(self))]
pub fn configure_expr(&self, expr: &mut P<ast::Expr>, method_receiver: bool) {
if !method_receiver {
for attr in expr.attrs.iter() {
self.maybe_emit_expr_attr_err(attr);
}
}
// If an expr is valid to cfg away it will have been removed by the

View file

@ -50,6 +50,7 @@ macro_rules! ast_fragments {
/// Can also serve as an input and intermediate result for macro expansion operations.
pub enum AstFragment {
OptExpr(Option<P<ast::Expr>>),
MethodReceiverExpr(P<ast::Expr>),
$($Kind($AstTy),)*
}
@ -57,6 +58,7 @@ macro_rules! ast_fragments {
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum AstFragmentKind {
OptExpr,
MethodReceiverExpr,
$($Kind,)*
}
@ -64,6 +66,7 @@ macro_rules! ast_fragments {
pub fn name(self) -> &'static str {
match self {
AstFragmentKind::OptExpr => "expression",
AstFragmentKind::MethodReceiverExpr => "expression",
$(AstFragmentKind::$Kind => $kind_name,)*
}
}
@ -72,6 +75,8 @@ macro_rules! ast_fragments {
match self {
AstFragmentKind::OptExpr =>
result.make_expr().map(Some).map(AstFragment::OptExpr),
AstFragmentKind::MethodReceiverExpr =>
result.make_expr().map(AstFragment::MethodReceiverExpr),
$(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
}
}
@ -98,6 +103,13 @@ macro_rules! ast_fragments {
}
}
pub fn make_method_receiver_expr(self) -> P<ast::Expr> {
match self {
AstFragment::MethodReceiverExpr(expr) => expr,
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
}
}
$(pub fn $make_ast(self) -> $AstTy {
match self {
AstFragment::$Kind(ast) => ast,
@ -120,6 +132,7 @@ macro_rules! ast_fragments {
}
});
}
AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
$($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
$($(AstFragment::$Kind(ast) =>
ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)*
@ -130,6 +143,7 @@ macro_rules! ast_fragments {
match *self {
AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
AstFragment::OptExpr(None) => {}
AstFragment::MethodReceiverExpr(ref expr) => visitor.visit_method_receiver_expr(expr),
$($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
$($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
visitor.$visit_ast_elt(ast_elt, $($args)*);
@ -222,6 +236,7 @@ impl AstFragmentKind {
match self {
AstFragmentKind::OptExpr
| AstFragmentKind::Expr
| AstFragmentKind::MethodReceiverExpr
| AstFragmentKind::Stmts
| AstFragmentKind::Ty
| AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false },
@ -285,6 +300,9 @@ impl AstFragmentKind {
AstFragmentKind::Expr => AstFragment::Expr(
items.next().expect("expected exactly one expression").expect_expr(),
),
AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(
items.next().expect("expected exactly one expression").expect_expr(),
),
AstFragmentKind::OptExpr => {
AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
}
@ -893,6 +911,7 @@ pub fn parse_ast_fragment<'a>(
AstFragment::Stmts(stmts)
}
AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(this.parse_expr()?),
AstFragmentKind::OptExpr => {
if this.token != token::Eof {
AstFragment::OptExpr(Some(this.parse_expr()?))
@ -1477,6 +1496,42 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
}
}
/// This struct is a hack to workaround unstable of `stmt_expr_attributes`.
/// It can be removed once that feature is stabilized.
struct MethodReceiverTag;
impl DummyAstNode for MethodReceiverTag {
fn dummy() -> MethodReceiverTag {
MethodReceiverTag
}
}
impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> {
type OutputTy = Self;
type AttrsTy = ast::AttrVec;
const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
fn descr() -> &'static str {
"an expression"
}
fn to_annotatable(self) -> Annotatable {
Annotatable::Expr(self.wrapped)
}
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag)
}
fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
noop_visit_expr(&mut self.wrapped, visitor)
}
fn is_mac_call(&self) -> bool {
matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
}
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
let node = self.wrapped.into_inner();
match node.kind {
ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
_ => unreachable!(),
}
}
}
struct InvocationCollector<'a, 'b> {
cx: &'a mut ExtCtxt<'b>,
invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
@ -1840,6 +1895,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
self.visit_node(node)
}
fn visit_method_receiver_expr(&mut self, node: &mut P<ast::Expr>) {
visit_clobber(node, |node| {
let mut wrapper = AstNodeWrapper::new(node, MethodReceiverTag);
self.visit_node(&mut wrapper);
wrapper.wrapped
})
}
fn filter_map_expr(&mut self, node: P<ast::Expr>) -> Option<P<ast::Expr>> {
self.flat_map_node(AstNodeWrapper::new(node, OptExprTag))
}

View file

@ -250,6 +250,7 @@ fn expand_macro<'cx>(
// hacky, but speeds up the `html5ever` benchmark significantly. (Issue
// 68836 suggests a more comprehensive but more complex change to deal with
// this situation.)
// FIXME(Nilstrieb): Stop recovery from happening on this parser and retry later with recovery if the macro failed to match.
let parser = parser_from_cx(sess, arg.clone());
// Try each arm's matchers.

View file

@ -55,6 +55,7 @@ pub fn placeholder(
}),
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(expr_placeholder()),
AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
id,
span,
@ -296,6 +297,13 @@ impl MutVisitor for PlaceholderExpander {
}
}
fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
match expr.kind {
ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(),
_ => noop_visit_expr(expr, self),
}
}
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
match expr.kind {
ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),

View file

@ -53,6 +53,8 @@ declare_features! (
(accepted, abi_sysv64, "1.24.0", Some(36167), None),
/// Allows using ADX intrinsics from `core::arch::{x86, x86_64}`.
(accepted, adx_target_feature, "1.61.0", Some(44839), None),
/// Allows explicit discriminants on non-unit enum variants.
(accepted, arbitrary_enum_discriminant, "CURRENT_RUSTC_VERSION", Some(60553), None),
/// Allows using `sym` operands in inline assembly.
(accepted, asm_sym, "CURRENT_RUSTC_VERSION", Some(93333), None),
/// Allows the definition of associated constants in `trait` or `impl` blocks.

View file

@ -292,8 +292,6 @@ declare_features! (
(incomplete, adt_const_params, "1.56.0", Some(95174), None),
/// Allows defining an `#[alloc_error_handler]`.
(active, alloc_error_handler, "1.29.0", Some(51540), None),
/// Allows explicit discriminants on non-unit enum variants.
(active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
/// Allows trait methods with arbitrary self types.
(active, arbitrary_self_types, "1.23.0", Some(44874), None),
/// Allows using `const` operands in inline assembly.

View file

@ -2207,14 +2207,14 @@ pub struct FnSig<'hir> {
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct TraitItemId {
pub def_id: OwnerId,
pub owner_id: OwnerId,
}
impl TraitItemId {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
HirId::make_owner(self.def_id.def_id)
HirId::make_owner(self.owner_id.def_id)
}
}
@ -2225,7 +2225,7 @@ impl TraitItemId {
#[derive(Debug, HashStable_Generic)]
pub struct TraitItem<'hir> {
pub ident: Ident,
pub def_id: OwnerId,
pub owner_id: OwnerId,
pub generics: &'hir Generics<'hir>,
pub kind: TraitItemKind<'hir>,
pub span: Span,
@ -2236,11 +2236,11 @@ impl TraitItem<'_> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
HirId::make_owner(self.def_id.def_id)
HirId::make_owner(self.owner_id.def_id)
}
pub fn trait_item_id(&self) -> TraitItemId {
TraitItemId { def_id: self.def_id }
TraitItemId { owner_id: self.owner_id }
}
}
@ -2271,14 +2271,14 @@ pub enum TraitItemKind<'hir> {
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct ImplItemId {
pub def_id: OwnerId,
pub owner_id: OwnerId,
}
impl ImplItemId {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
HirId::make_owner(self.def_id.def_id)
HirId::make_owner(self.owner_id.def_id)
}
}
@ -2286,7 +2286,7 @@ impl ImplItemId {
#[derive(Debug, HashStable_Generic)]
pub struct ImplItem<'hir> {
pub ident: Ident,
pub def_id: OwnerId,
pub owner_id: OwnerId,
pub generics: &'hir Generics<'hir>,
pub kind: ImplItemKind<'hir>,
pub defaultness: Defaultness,
@ -2298,11 +2298,11 @@ impl ImplItem<'_> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
HirId::make_owner(self.def_id.def_id)
HirId::make_owner(self.owner_id.def_id)
}
pub fn impl_item_id(&self) -> ImplItemId {
ImplItemId { def_id: self.def_id }
ImplItemId { owner_id: self.owner_id }
}
}
@ -2418,6 +2418,30 @@ impl<'hir> Ty<'hir> {
}
final_ty
}
pub fn find_self_aliases(&self) -> Vec<Span> {
use crate::intravisit::Visitor;
struct MyVisitor(Vec<Span>);
impl<'v> Visitor<'v> for MyVisitor {
fn visit_ty(&mut self, t: &'v Ty<'v>) {
if matches!(
&t.kind,
TyKind::Path(QPath::Resolved(
_,
Path { res: crate::def::Res::SelfTyAlias { .. }, .. },
))
) {
self.0.push(t.span);
return;
}
crate::intravisit::walk_ty(self, t);
}
}
let mut my_visitor = MyVisitor(vec![]);
my_visitor.visit_ty(self);
my_visitor.0
}
}
/// Not represented directly in the AST; referred to by name through a `ty_path`.
@ -2890,14 +2914,14 @@ impl<'hir> VariantData<'hir> {
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
pub struct ItemId {
pub def_id: OwnerId,
pub owner_id: OwnerId,
}
impl ItemId {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
HirId::make_owner(self.def_id.def_id)
HirId::make_owner(self.owner_id.def_id)
}
}
@ -2907,7 +2931,7 @@ impl ItemId {
#[derive(Debug, HashStable_Generic)]
pub struct Item<'hir> {
pub ident: Ident,
pub def_id: OwnerId,
pub owner_id: OwnerId,
pub kind: ItemKind<'hir>,
pub span: Span,
pub vis_span: Span,
@ -2917,11 +2941,11 @@ impl Item<'_> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
HirId::make_owner(self.def_id.def_id)
HirId::make_owner(self.owner_id.def_id)
}
pub fn item_id(&self) -> ItemId {
ItemId { def_id: self.def_id }
ItemId { owner_id: self.owner_id }
}
}
@ -3134,14 +3158,14 @@ pub enum AssocItemKind {
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct ForeignItemId {
pub def_id: OwnerId,
pub owner_id: OwnerId,
}
impl ForeignItemId {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
HirId::make_owner(self.def_id.def_id)
HirId::make_owner(self.owner_id.def_id)
}
}
@ -3162,7 +3186,7 @@ pub struct ForeignItemRef {
pub struct ForeignItem<'hir> {
pub ident: Ident,
pub kind: ForeignItemKind<'hir>,
pub def_id: OwnerId,
pub owner_id: OwnerId,
pub span: Span,
pub vis_span: Span,
}
@ -3171,11 +3195,11 @@ impl ForeignItem<'_> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
HirId::make_owner(self.def_id.def_id)
HirId::make_owner(self.owner_id.def_id)
}
pub fn foreign_item_id(&self) -> ForeignItemId {
ForeignItemId { def_id: self.def_id }
ForeignItemId { owner_id: self.owner_id }
}
}
@ -3267,10 +3291,10 @@ impl<'hir> OwnerNode<'hir> {
pub fn def_id(self) -> OwnerId {
match self {
OwnerNode::Item(Item { def_id, .. })
| OwnerNode::TraitItem(TraitItem { def_id, .. })
| OwnerNode::ImplItem(ImplItem { def_id, .. })
| OwnerNode::ForeignItem(ForeignItem { def_id, .. }) => *def_id,
OwnerNode::Item(Item { owner_id, .. })
| OwnerNode::TraitItem(TraitItem { owner_id, .. })
| OwnerNode::ImplItem(ImplItem { owner_id, .. })
| OwnerNode::ForeignItem(ForeignItem { owner_id, .. }) => *owner_id,
OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
}
}

View file

@ -912,7 +912,7 @@ pub fn walk_fn<'v, V: Visitor<'v>>(
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
// N.B., deliberately force a compilation error if/when new fields are added.
let TraitItem { ident, generics, ref defaultness, ref kind, span, def_id: _ } = *trait_item;
let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item;
let hir_id = trait_item.hir_id();
visitor.visit_ident(ident);
visitor.visit_generics(&generics);
@ -952,7 +952,7 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:
pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
// N.B., deliberately force a compilation error if/when new fields are added.
let ImplItem {
def_id: _,
owner_id: _,
ident,
ref generics,
ref kind,

View file

@ -49,7 +49,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ItemId {
#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
self.def_id.def_id.to_stable_hash_key(hcx)
self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
@ -58,7 +58,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId {
#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
self.def_id.def_id.to_stable_hash_key(hcx)
self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
@ -67,7 +67,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
self.def_id.def_id.to_stable_hash_key(hcx)
self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
@ -76,7 +76,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId
#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
self.def_id.def_id.to_stable_hash_key(hcx)
self.owner_id.def_id.to_stable_hash_key(hcx)
}
}

View file

@ -36,7 +36,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
use rustc_span::edition::Edition;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::Span;
use rustc_span::{sym, Span};
use rustc_target::spec::abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::astconv_object_safety_violations;
@ -275,6 +275,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_segment.args(),
item_segment.infer_args,
None,
None,
);
if let Some(b) = item_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
@ -324,6 +325,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
generic_args: &'a hir::GenericArgs<'_>,
infer_args: bool,
self_ty: Option<Ty<'tcx>>,
constness: Option<ty::BoundConstness>,
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
// If the type is parameterized by this region, then replace this
// region with the current anon region binding (in other words,
@ -534,6 +536,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&mut substs_ctx,
);
if let Some(ty::BoundConstness::ConstIfConst) = constness
&& generics.has_self && !tcx.has_attr(def_id, sym::const_trait)
{
tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } );
}
(substs, arg_count)
}
@ -601,6 +609,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_segment.args(),
item_segment.infer_args,
None,
None,
);
if let Some(b) = item_segment.args().bindings.first() {
@ -620,6 +629,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
trait_ref: &hir::TraitRef<'_>,
self_ty: Ty<'tcx>,
constness: ty::BoundConstness,
) -> ty::TraitRef<'tcx> {
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
@ -629,6 +639,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty,
trait_ref.path.segments.last().unwrap(),
true,
Some(constness),
)
}
@ -655,6 +666,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args,
infer_args,
Some(self_ty),
Some(constness),
);
let tcx = self.tcx();
@ -680,6 +692,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
speculative,
&mut dup_bindings,
binding_span.unwrap_or(binding.span),
constness,
);
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
}
@ -783,6 +796,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment<'_>,
is_impl: bool,
constness: Option<ty::BoundConstness>,
) -> ty::TraitRef<'tcx> {
let (substs, _) = self.create_substs_for_ast_trait_ref(
span,
@ -790,6 +804,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty,
trait_segment,
is_impl,
constness,
);
if let Some(b) = trait_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
@ -805,6 +820,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty: Ty<'tcx>,
trait_segment: &'a hir::PathSegment<'a>,
is_impl: bool,
constness: Option<ty::BoundConstness>,
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
@ -816,6 +832,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_segment.args(),
trait_segment.infer_args,
Some(self_ty),
constness,
)
}
@ -1027,6 +1044,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
speculative: bool,
dup_bindings: &mut FxHashMap<DefId, Span>,
path_span: Span,
constness: ty::BoundConstness,
) -> Result<(), ErrorGuaranteed> {
// Given something like `U: SomeTrait<T = X>`, we want to produce a
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
@ -1122,10 +1140,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_ref.substs,
);
debug!(
"add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}",
substs_trait_ref_and_assoc_item
);
debug!(?substs_trait_ref_and_assoc_item);
ty::ProjectionTy {
item_def_id: assoc_item.def_id,
@ -1146,8 +1161,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.collect_constrained_late_bound_regions(&projection_ty);
let late_bound_in_ty =
tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty));
debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
debug!(?late_bound_in_trait_ref);
debug!(?late_bound_in_ty);
// FIXME: point at the type params that don't have appropriate lifetimes:
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
@ -1648,6 +1663,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Checks that `bounds` contains exactly one element and reports appropriate
// errors otherwise.
#[instrument(level = "debug", skip(self, all_candidates, ty_param_name, is_equality), ret)]
fn one_bound_for_assoc_type<I>(
&self,
all_candidates: impl Fn() -> I,
@ -1677,10 +1693,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
return Err(reported);
}
};
debug!("one_bound_for_assoc_type: bound = {:?}", bound);
debug!(?bound);
if let Some(bound2) = next_cand {
debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
debug!(?bound2);
let is_equality = is_equality();
let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
@ -1776,6 +1792,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// parameter or `Self`.
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
#[instrument(level = "debug", skip(self, hir_ref_id, span, qself, assoc_segment), fields(assoc_ident=?assoc_segment.ident), ret)]
pub fn associated_path_to_ty(
&self,
hir_ref_id: hir::HirId,
@ -1793,8 +1810,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Res::Err
};
debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
// Check if we have an enum variant.
let mut variant_resolution = None;
if let ty::Adt(adt_def, _) = qself_ty.kind() {
@ -2050,6 +2065,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_def_id: DefId,
trait_segment: &hir::PathSegment<'_>,
item_segment: &hir::PathSegment<'_>,
constness: ty::BoundConstness,
) -> Ty<'tcx> {
let tcx = self.tcx();
@ -2094,8 +2110,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("qpath_to_ty: self_type={:?}", self_ty);
let trait_ref =
self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
let trait_ref = self.ast_path_to_mono_trait_ref(
span,
trait_def_id,
self_ty,
trait_segment,
false,
Some(constness),
);
let item_substs = self.create_substs_for_associated_item(
span,
@ -2534,12 +2556,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Res::Def(DefKind::AssocTy, def_id) => {
debug_assert!(path.segments.len() >= 2);
self.prohibit_generics(path.segments[..path.segments.len() - 2].iter(), |_| {});
// HACK: until we support `<Type as ~const Trait>`, assume all of them are.
let constness = if tcx.has_attr(tcx.parent(def_id), sym::const_trait) {
ty::BoundConstness::ConstIfConst
} else {
ty::BoundConstness::NotConst
};
self.qpath_to_ty(
span,
opt_self_ty,
def_id,
&path.segments[path.segments.len() - 2],
path.segments.last().unwrap(),
constness,
)
}
Res::PrimTy(prim_ty) => {
@ -2632,7 +2661,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
let opaque_ty = tcx.hir().item(item_id);
let def_id = item_id.def_id.to_def_id();
let def_id = item_id.owner_id.to_def_id();
match opaque_ty.kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
@ -2658,6 +2687,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&GenericArgs::none(),
true,
None,
None,
);
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
.subst(tcx, substs)
@ -2766,6 +2796,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
#[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)]
pub fn ty_of_fn(
&self,
hir_id: hir::HirId,
@ -2775,8 +2806,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
generics: Option<&hir::Generics<'_>>,
hir_ty: Option<&hir::Ty<'_>>,
) -> ty::PolyFnSig<'tcx> {
debug!("ty_of_fn");
let tcx = self.tcx();
let bound_vars = tcx.late_bound_vars(hir_id);
debug!(?bound_vars);
@ -2826,7 +2855,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
};
debug!("ty_of_fn: output_ty={:?}", output_ty);
debug!(?output_ty);
let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi);
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
@ -2903,8 +2932,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") };
let trait_ref =
self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
let trait_ref = self.instantiate_mono_trait_ref(
i.of_trait.as_ref()?,
self.ast_ty_to_ty(i.self_ty),
ty::BoundConstness::NotConst,
);
let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
tcx,

View file

@ -114,7 +114,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
_ => {
// Fallback case: allow `ManuallyDrop` and things that are `Copy`.
ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop())
|| ty.is_copy_modulo_regions(tcx.at(span), param_env)
|| ty.is_copy_modulo_regions(tcx, param_env)
}
}
}
@ -227,17 +227,17 @@ fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
return;
}
let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
let span = tcx.def_span(item.def_id.def_id);
let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id());
let span = tcx.def_span(item.owner_id.def_id);
check_opaque_for_inheriting_lifetimes(tcx, item.def_id.def_id, span);
if tcx.type_of(item.def_id.def_id).references_error() {
check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span);
if tcx.type_of(item.owner_id.def_id).references_error() {
return;
}
if check_opaque_for_cycles(tcx, item.def_id.def_id, substs, span, &origin).is_err() {
if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
return;
}
check_opaque_meets_bounds(tcx, item.def_id.def_id, substs, span, &origin);
check_opaque_meets_bounds(tcx, item.owner_id.def_id, substs, span, &origin);
}
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
/// in "inheriting lifetimes".
@ -492,25 +492,25 @@ fn check_opaque_meets_bounds<'tcx>(
fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
debug!(
"check_item_type(it.def_id={:?}, it.name={})",
id.def_id,
tcx.def_path_str(id.def_id.to_def_id())
id.owner_id,
tcx.def_path_str(id.owner_id.to_def_id())
);
let _indenter = indenter();
match tcx.def_kind(id.def_id) {
match tcx.def_kind(id.owner_id) {
DefKind::Static(..) => {
tcx.ensure().typeck(id.def_id.def_id);
maybe_check_static_with_link_section(tcx, id.def_id.def_id);
check_static_inhabited(tcx, id.def_id.def_id);
tcx.ensure().typeck(id.owner_id.def_id);
maybe_check_static_with_link_section(tcx, id.owner_id.def_id);
check_static_inhabited(tcx, id.owner_id.def_id);
}
DefKind::Const => {
tcx.ensure().typeck(id.def_id.def_id);
tcx.ensure().typeck(id.owner_id.def_id);
}
DefKind::Enum => {
let item = tcx.hir().item(id);
let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else {
return;
};
check_enum(tcx, &enum_definition.variants, item.def_id.def_id);
check_enum(tcx, &enum_definition.variants, item.owner_id.def_id);
}
DefKind::Fn => {} // entirely within check_item_body
DefKind::Impl => {
@ -518,12 +518,12 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
let hir::ItemKind::Impl(ref impl_) = it.kind else {
return;
};
debug!("ItemKind::Impl {} with id {:?}", it.ident, it.def_id);
if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) {
debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id);
if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) {
check_impl_items_against_trait(
tcx,
it.span,
it.def_id.def_id,
it.owner_id.def_id,
impl_trait_ref,
&impl_.items,
);
@ -545,15 +545,15 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
fn_maybe_err(tcx, item.ident.span, abi);
}
hir::TraitItemKind::Type(.., Some(default)) => {
let assoc_item = tcx.associated_item(item.def_id);
let assoc_item = tcx.associated_item(item.owner_id);
let trait_substs =
InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id());
InternalSubsts::identity_for_item(tcx, it.owner_id.to_def_id());
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
tcx,
assoc_item,
assoc_item,
default.span,
ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs },
ty::TraitRef { def_id: it.owner_id.to_def_id(), substs: trait_substs },
);
}
_ => {}
@ -561,16 +561,16 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
}
}
DefKind::Struct => {
check_struct(tcx, id.def_id.def_id);
check_struct(tcx, id.owner_id.def_id);
}
DefKind::Union => {
check_union(tcx, id.def_id.def_id);
check_union(tcx, id.owner_id.def_id);
}
DefKind::OpaqueTy => {
check_opaque(tcx, id);
}
DefKind::ImplTraitPlaceholder => {
let parent = tcx.impl_trait_in_trait_parent(id.def_id.to_def_id());
let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id());
// Only check the validity of this opaque type if the function has a default body
if let hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
@ -581,8 +581,8 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
}
}
DefKind::TyAlias => {
let pty_ty = tcx.type_of(id.def_id);
let generics = tcx.generics_of(id.def_id);
let pty_ty = tcx.type_of(id.owner_id);
let generics = tcx.generics_of(id.owner_id);
check_type_params_are_used(tcx, &generics, pty_ty);
}
DefKind::ForeignMod => {
@ -604,7 +604,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
}
} else {
for item in items {
let def_id = item.id.def_id.def_id;
let def_id = item.id.owner_id.def_id;
let generics = tcx.generics_of(def_id);
let own_counts = generics.own_counts();
if generics.params.len() - own_counts.lifetimes != 0 {
@ -659,7 +659,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
// an error would be reported if this fails.
let _ = traits::OnUnimplementedDirective::of_item(tcx, item.def_id.to_def_id());
let _ = traits::OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
}
pub(super) fn check_specialization_validity<'tcx>(
@ -746,7 +746,7 @@ 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.def_id);
let ty_impl_item = tcx.associated_item(impl_item.id.owner_id);
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
tcx.associated_item(trait_item_id)
} else {
@ -758,7 +758,7 @@ fn check_impl_items_against_trait<'tcx>(
match impl_item_full.kind {
hir::ImplItemKind::Const(..) => {
let _ = tcx.compare_assoc_const_impl_item_with_trait_item((
impl_item.id.def_id.def_id,
impl_item.id.owner_id.def_id,
ty_impl_item.trait_item_def_id.unwrap(),
));
}
@ -1180,7 +1180,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
}
}
if tcx.adt_def(def_id).repr().int.is_none() && tcx.features().arbitrary_enum_discriminant {
if tcx.adt_def(def_id).repr().int.is_none() {
let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();

View file

@ -597,7 +597,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
let num_trait_substs = trait_to_impl_substs.len();
let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
let ty = tcx.fold_regions(ty, |region, _| {
let ty::ReFree(_) = region.kind() else { return region; };
let (ty::ReFree(_) | ty::ReEarlyBound(_)) = region.kind() else { return region; };
let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
else {
tcx

View file

@ -26,7 +26,7 @@ fn equate_intrinsic_type<'tcx>(
) {
let (own_counts, span) = match &it.kind {
hir::ForeignItemKind::Fn(.., generics) => {
let own_counts = tcx.generics_of(it.def_id.to_def_id()).own_counts();
let own_counts = tcx.generics_of(it.owner_id.to_def_id()).own_counts();
(own_counts, generics.span)
}
_ => {
@ -57,7 +57,7 @@ fn equate_intrinsic_type<'tcx>(
{
let fty = tcx.mk_fn_ptr(sig);
let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType);
require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty);
require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id)), fty);
}
}
@ -129,7 +129,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
/// and in `library/core/src/intrinsics.rs`.
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
let intrinsic_id = it.def_id.to_def_id();
let intrinsic_id = it.owner_id.to_def_id();
let intrinsic_name = tcx.item_name(intrinsic_id);
let name_str = intrinsic_name.as_str();

View file

@ -33,7 +33,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
// Type still may have region variables, but `Sized` does not depend
// on those, so just erase them before querying.
if ty.is_sized(self.tcx.at(DUMMY_SP), self.param_env) {
if ty.is_sized(self.tcx, self.param_env) {
return true;
}
if let ty::Foreign(..) = ty.kind() {
@ -128,7 +128,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check that the type implements Copy. The only case where this can
// possibly fail is for SIMD types which don't #[derive(Copy)].
if !ty.is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env) {
if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
let msg = "arguments for inline assembly must be copyable";
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
err.note(&format!("`{ty}` does not implement the Copy trait"));

View file

@ -147,10 +147,10 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
/// the types first.
#[instrument(skip(tcx), level = "debug")]
fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
let def_id = item.def_id.def_id;
let def_id = item.owner_id.def_id;
debug!(
?item.def_id,
?item.owner_id,
item.name = ? tcx.def_path_str(def_id.to_def_id())
);
@ -246,10 +246,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
let def_id = item.def_id.def_id;
let def_id = item.owner_id.def_id;
debug!(
?item.def_id,
?item.owner_id,
item.name = ? tcx.def_path_str(def_id.to_def_id())
);
@ -263,7 +263,7 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
}
fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
let def_id = trait_item.def_id.def_id;
let def_id = trait_item.owner_id.def_id;
let (method_sig, span) = match trait_item.kind {
hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
@ -275,7 +275,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
let encl_trait_def_id = tcx.local_parent(def_id);
let encl_trait = tcx.hir().expect_item(encl_trait_def_id);
let encl_trait_def_id = encl_trait.def_id.to_def_id();
let encl_trait_def_id = encl_trait.owner_id.to_def_id();
let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() {
Some("fn")
} else if Some(encl_trait_def_id) == tcx.lang_items().fn_mut_trait() {
@ -348,7 +348,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
loop {
let mut should_continue = false;
for gat_item in associated_items {
let gat_def_id = gat_item.id.def_id;
let gat_def_id = gat_item.id.owner_id;
let gat_item = tcx.associated_item(gat_def_id);
// If this item is not an assoc ty, or has no substs, then it's not a GAT
if gat_item.kind != ty::AssocKind::Type {
@ -365,7 +365,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
// constrains the GAT with individually.
let mut new_required_bounds: Option<FxHashSet<ty::Predicate<'_>>> = None;
for item in associated_items {
let item_def_id = item.id.def_id;
let item_def_id = item.id.owner_id;
// Skip our own GAT, since it does not constrain itself at all.
if item_def_id == gat_def_id {
continue;
@ -713,6 +713,10 @@ fn resolve_regions_with_wf_tys<'tcx>(
add_constraints(&infcx, region_bound_pairs);
infcx.process_registered_region_obligations(
outlives_environment.region_bound_pairs(),
param_env,
);
let errors = infcx.resolve_regions(&outlives_environment);
debug!(?errors, "errors");
@ -786,7 +790,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
let (trait_name, trait_def_id) =
match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) {
hir::Node::Item(item) => match item.kind {
hir::ItemKind::Trait(..) => (item.ident, item.def_id),
hir::ItemKind::Trait(..) => (item.ident, item.owner_id),
_ => return,
},
_ => return,
@ -841,7 +845,7 @@ fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) {
_ => (None, impl_item.span),
};
check_associated_item(tcx, impl_item.def_id.def_id, span, method_sig);
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig);
}
fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
@ -1041,11 +1045,11 @@ fn check_type_defn<'tcx, F>(
) where
F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec<AdtVariant<'tcx>>,
{
let _ = tcx.representability(item.def_id.def_id);
let _ = tcx.representability(item.owner_id.def_id);
enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| {
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
let variants = lookup_fields(wfcx);
let packed = tcx.adt_def(item.def_id).repr().packed();
let packed = tcx.adt_def(item.owner_id).repr().packed();
for variant in &variants {
// All field types must be well-formed.
@ -1069,7 +1073,7 @@ fn check_type_defn<'tcx, F>(
// Just treat unresolved type expression as if it needs drop.
true
} else {
ty.needs_drop(tcx, tcx.param_env(item.def_id))
ty.needs_drop(tcx, tcx.param_env(item.owner_id))
}
}
};
@ -1117,15 +1121,15 @@ fn check_type_defn<'tcx, F>(
}
}
check_where_clauses(wfcx, item.span, item.def_id.def_id);
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
});
}
#[instrument(skip(tcx, item))]
fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
debug!(?item.def_id);
debug!(?item.owner_id);
let def_id = item.def_id.def_id;
let def_id = item.owner_id.def_id;
let trait_def = tcx.trait_def(def_id);
if trait_def.is_marker
|| matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
@ -1236,13 +1240,13 @@ fn check_impl<'tcx>(
ast_trait_ref: &Option<hir::TraitRef<'_>>,
constness: hir::Constness,
) {
enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| {
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
match *ast_trait_ref {
Some(ref ast_trait_ref) => {
// `#[rustc_reservation_impl]` impls are not real impls and
// therefore don't need to be WF (the trait's `Self: Trait` predicate
// won't hold).
let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap();
let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap();
let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref);
let trait_pred = ty::TraitPredicate {
trait_ref,
@ -1264,7 +1268,7 @@ fn check_impl<'tcx>(
wfcx.register_obligations(obligations);
}
None => {
let self_ty = tcx.type_of(item.def_id);
let self_ty = tcx.type_of(item.owner_id);
let self_ty = wfcx.normalize(
item.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
@ -1278,7 +1282,7 @@ fn check_impl<'tcx>(
}
}
check_where_clauses(wfcx, item.span, item.def_id.def_id);
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
});
}
@ -1774,14 +1778,14 @@ fn check_variances_for_type_defn<'tcx>(
item: &hir::Item<'tcx>,
hir_generics: &hir::Generics<'_>,
) {
let ty = tcx.type_of(item.def_id);
let ty = tcx.type_of(item.owner_id);
if tcx.has_error_field(ty) {
return;
}
let ty_predicates = tcx.predicates_of(item.def_id);
let ty_predicates = tcx.predicates_of(item.owner_id);
assert_eq!(ty_predicates.parent, None);
let variances = tcx.variances_of(item.def_id);
let variances = tcx.variances_of(item.owner_id);
let mut constrained_parameters: FxHashSet<_> = variances
.iter()
@ -1794,7 +1798,7 @@ fn check_variances_for_type_defn<'tcx>(
// Lazily calculated because it is only needed in case of an error.
let explicitly_bounded_params = LazyCell::new(|| {
let icx = crate::collect::ItemCtxt::new(tcx, item.def_id.to_def_id());
let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.to_def_id());
hir_generics
.predicates
.iter()
@ -1915,10 +1919,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) {
let items = tcx.hir_module_items(module);
items.par_items(|item| tcx.ensure().check_well_formed(item.def_id));
items.par_impl_items(|item| tcx.ensure().check_well_formed(item.def_id));
items.par_trait_items(|item| tcx.ensure().check_well_formed(item.def_id));
items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.def_id));
items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id));
items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id));
items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id));
}
///////////////////////////////////////////////////////////////////////////

View file

@ -1,5 +1,6 @@
use crate::errors::{ExternCrateNotIdiomatic, UnusedExternCrate};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::unord::UnordSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
@ -8,12 +9,12 @@ use rustc_session::lint;
use rustc_span::{Span, Symbol};
pub fn check_crate(tcx: TyCtxt<'_>) {
let mut used_trait_imports: FxHashSet<LocalDefId> = FxHashSet::default();
let mut used_trait_imports: UnordSet<LocalDefId> = Default::default();
for item_def_id in tcx.hir().body_owners() {
let imports = tcx.used_trait_imports(item_def_id);
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
used_trait_imports.extend(imports.iter());
used_trait_imports.extend(imports.items().copied());
}
for &id in tcx.maybe_unused_trait_imports(()) {
@ -89,11 +90,11 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
let mut crates_to_lint = vec![];
for id in tcx.hir().items() {
if matches!(tcx.def_kind(id.def_id), DefKind::ExternCrate) {
if matches!(tcx.def_kind(id.owner_id), DefKind::ExternCrate) {
let item = tcx.hir().item(id);
if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
crates_to_lint.push(ExternCrateToLint {
def_id: item.def_id.to_def_id(),
def_id: item.owner_id.to_def_id(),
span: item.span,
orig_name,
warn_if_unused: !item.ident.as_str().starts_with('_'),

View file

@ -58,7 +58,7 @@ const ADD_ATTR: &str =
impl<'tcx> InherentCollect<'tcx> {
fn check_def_id(&mut self, item: &hir::Item<'_>, self_ty: Ty<'tcx>, def_id: DefId) {
let impl_def_id = item.def_id;
let impl_def_id = item.owner_id;
if let Some(def_id) = 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
@ -89,7 +89,7 @@ impl<'tcx> InherentCollect<'tcx> {
for impl_item in items {
if !self
.tcx
.has_attr(impl_item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl)
.has_attr(impl_item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
{
struct_span_err!(
self.tcx.sess,
@ -135,7 +135,7 @@ impl<'tcx> InherentCollect<'tcx> {
for item in items {
if !self
.tcx
.has_attr(item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl)
.has_attr(item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
{
struct_span_err!(
self.tcx.sess,
@ -177,7 +177,7 @@ impl<'tcx> InherentCollect<'tcx> {
}
fn check_item(&mut self, id: hir::ItemId) {
if !matches!(self.tcx.def_kind(id.def_id), DefKind::Impl) {
if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl) {
return;
}
@ -186,7 +186,7 @@ impl<'tcx> InherentCollect<'tcx> {
return;
};
let self_ty = self.tcx.type_of(item.def_id);
let self_ty = self.tcx.type_of(item.owner_id);
match *self_ty.kind() {
ty::Adt(def, _) => {
self.check_def_id(item, self_ty, def.did());
@ -221,7 +221,7 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Never
| ty::FnPtr(_)
| ty::Tuple(..) => {
self.check_primitive_impl(item.def_id.def_id, self_ty, items, ty.span)
self.check_primitive_impl(item.owner_id.def_id, self_ty, items, ty.span)
}
ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
let mut err = struct_span_err!(
@ -243,7 +243,7 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => {
bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty);
bug!("unexpected impl self type of impl: {:?} {:?}", item.owner_id, self_ty);
}
ty::Error(_) => {}
}

View file

@ -156,14 +156,14 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
}
fn check_item(&mut self, id: hir::ItemId) {
let def_kind = self.tcx.def_kind(id.def_id);
let def_kind = self.tcx.def_kind(id.owner_id);
if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) {
return;
}
let impls = self.tcx.inherent_impls(id.def_id);
let impls = self.tcx.inherent_impls(id.owner_id);
let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id());
let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id());
let impls_items = impls
.iter()

View file

@ -101,7 +101,7 @@ fn do_orphan_check_impl<'tcx>(
span_bug!(sp, "opaque type not found, but `has_opaque_types` is set")
}
match traits::orphan_check(tcx, item.def_id.to_def_id()) {
match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
Ok(()) => {}
Err(err) => emit_orphan_check_error(
tcx,

View file

@ -13,7 +13,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let item = tcx.hir().expect_item(def_id);
let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() };
if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
let trait_def = tcx.trait_def(trait_ref.def_id);
let unsafe_attr =
impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
@ -26,6 +26,12 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"implementing the trait `{}` is not unsafe",
trait_ref.print_only_trait_path()
)
.span_suggestion_verbose(
item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)),
"remove `unsafe` from this trait implementation",
"",
rustc_errors::Applicability::MachineApplicable,
)
.emit();
}
@ -37,6 +43,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"the trait `{}` requires an `unsafe impl` declaration",
trait_ref.print_only_trait_path()
)
.note(format!(
"the trait `{}` enforces invariants that the compiler can't check. \
Review the trait documentation and make sure this implementation \
upholds those invariants before adding the `unsafe` keyword",
trait_ref.print_only_trait_path()
))
.span_suggestion_verbose(
item.span.shrink_to_lo(),
"add `unsafe` to this trait implementation",
"unsafe ",
rustc_errors::Applicability::MaybeIncorrect,
)
.emit();
}
@ -48,6 +66,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
attr_name
)
.note(format!(
"the trait `{}` enforces invariants that the compiler can't check. \
Review the trait documentation and make sure this implementation \
upholds those invariants before adding the `unsafe` keyword",
trait_ref.print_only_trait_path()
))
.span_suggestion_verbose(
item.span.shrink_to_lo(),
"add `unsafe` to this trait implementation",
"unsafe ",
rustc_errors::Applicability::MaybeIncorrect,
)
.emit();
}

View file

@ -571,7 +571,7 @@ fn get_new_lifetime_name<'tcx>(
fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
let it = tcx.hir().item(item_id);
debug!("convert: item {} with id {}", it.ident, it.hir_id());
let def_id = item_id.def_id.def_id;
let def_id = item_id.owner_id.def_id;
match it.kind {
// These don't define types.
@ -583,11 +583,11 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
hir::ItemKind::ForeignMod { items, .. } => {
for item in items {
let item = tcx.hir().foreign_item(item.id);
tcx.ensure().generics_of(item.def_id);
tcx.ensure().type_of(item.def_id);
tcx.ensure().predicates_of(item.def_id);
tcx.ensure().generics_of(item.owner_id);
tcx.ensure().type_of(item.owner_id);
tcx.ensure().predicates_of(item.owner_id);
match item.kind {
hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id),
hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.owner_id),
hir::ForeignItemKind::Static(..) => {
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_foreign_item(item);
@ -683,7 +683,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
let trait_item = tcx.hir().trait_item(trait_item_id);
let def_id = trait_item_id.def_id;
let def_id = trait_item_id.owner_id;
tcx.ensure().generics_of(def_id);
match trait_item.kind {
@ -730,7 +730,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
}
fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
let def_id = impl_item_id.def_id;
let def_id = impl_item_id.owner_id;
tcx.ensure().generics_of(def_id);
tcx.ensure().type_of(def_id);
tcx.ensure().predicates_of(def_id);
@ -1010,7 +1010,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
match item {
Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
if !tcx.impl_defaultness(item.id.def_id).has_value() {
if !tcx.impl_defaultness(item.id.owner_id).has_value() {
tcx.sess
.struct_span_err(
item.span,
@ -1143,7 +1143,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
}
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
// Do not try to inference the return type for a impl method coming from a trait
// Do not try to infer the return type for a impl method coming from a trait
if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
tcx.hir().get(tcx.hir().get_parent_node(hir_id))
&& i.of_trait.is_some()
@ -1286,15 +1286,46 @@ fn infer_return_ty_for_fn_sig<'tcx>(
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
let icx = ItemCtxt::new(tcx, def_id);
match tcx.hir().expect_item(def_id.expect_local()).kind {
let item = tcx.hir().expect_item(def_id.expect_local());
match item.kind {
hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id);
<dyn AstConv<'_>>::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
<dyn AstConv<'_>>::instantiate_mono_trait_ref(
&icx,
ast_trait_ref,
selfty,
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
)
}),
_ => bug!(),
}
}
fn check_impl_constness(
tcx: TyCtxt<'_>,
constness: hir::Constness,
ast_trait_ref: &hir::TraitRef<'_>,
) -> ty::BoundConstness {
match constness {
hir::Constness::Const => {
if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) {
let trait_name = tcx.item_name(trait_def_id).to_string();
tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
trait_ref_span: ast_trait_ref.path.span,
trait_name,
local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
marking: (),
adding: (),
});
ty::BoundConstness::NotConst
} else {
ty::BoundConstness::ConstIfConst
}
},
hir::Constness::NotConst => ty::BoundConstness::NotConst,
}
}
fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
let item = tcx.hir().expect_item(def_id.expect_local());

View file

@ -249,6 +249,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
// Now create the real type and const parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
let mut i = 0;
let mut next_index = || {
let prev = i;
i += 1;
prev as u32 + type_start
};
const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
`struct`, `enum`, `type`, or `trait` definitions";
@ -278,15 +283,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic };
let param_def = ty::GenericParamDef {
index: type_start + i as u32,
Some(ty::GenericParamDef {
index: next_index(),
name: param.name.ident().name,
def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
kind,
};
i += 1;
Some(param_def)
})
}
GenericParamKind::Const { default, .. } => {
if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
@ -297,15 +300,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
);
}
let param_def = ty::GenericParamDef {
index: type_start + i as u32,
Some(ty::GenericParamDef {
index: next_index(),
name: param.name.ident().name,
def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Const { has_default: default.is_some() },
};
i += 1;
Some(param_def)
})
}
}));
@ -323,8 +324,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
&["<closure_kind>", "<closure_signature>", "<upvars>"][..]
};
params.extend(dummy_args.iter().enumerate().map(|(i, &arg)| ty::GenericParamDef {
index: type_start + i as u32,
params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef {
index: next_index(),
name: Symbol::intern(arg),
def_id,
pure_wrt_drop: false,
@ -337,7 +338,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
params.push(ty::GenericParamDef {
index: type_start,
index: next_index(),
name: Symbol::intern("<const_ty>"),
def_id,
pure_wrt_drop: false,

View file

@ -331,8 +331,8 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime
/// `resolve_lifetimes`.
fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: hir::OwnerId) -> &'tcx ResolveLifetimes {
let item_id = item_for(tcx, def_id.def_id);
let local_def_id = item_id.def_id.def_id;
if item_id.def_id == def_id {
let local_def_id = item_id.owner_id.def_id;
if item_id.owner_id == def_id {
let item = tcx.hir().item(item_id);
match item.kind {
hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(local_def_id),
@ -557,11 +557,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// their owner, we can keep going until we find the Item that owns that. We then
// conservatively add all resolved lifetimes. Otherwise we run into problems in
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
for (_hir_id, node) in self.tcx.hir().parent_iter(item.def_id.into()) {
for (_hir_id, node) in self.tcx.hir().parent_iter(item.owner_id.into()) {
match node {
hir::Node::Item(parent_item) => {
let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(
item_for(self.tcx, parent_item.def_id.def_id).def_id.def_id,
item_for(self.tcx, parent_item.owner_id.def_id).owner_id.def_id,
);
// We need to add *all* deps, since opaque tys may want them from *us*
for (&owner, defs) in resolved_lifetimes.defs.iter() {

View file

@ -319,7 +319,15 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
}
}
ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty),
ItemKind::Impl(hir::Impl { self_ty, .. }) => icx.to_ty(*self_ty),
ItemKind::Impl(hir::Impl { self_ty, .. }) => {
match self_ty.find_self_aliases() {
spans if spans.len() > 0 => {
tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: (), });
tcx.ty_error()
},
_ => icx.to_ty(*self_ty),
}
},
ItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
tcx.mk_fn_def(def_id.to_def_id(), substs)
@ -635,24 +643,24 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
intravisit::walk_expr(self, ex);
}
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
trace!(?it.def_id);
trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
if it.def_id.def_id != self.def_id {
self.check(it.def_id.def_id);
if it.owner_id.def_id != self.def_id {
self.check(it.owner_id.def_id);
intravisit::walk_item(self, it);
}
}
fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
trace!(?it.def_id);
trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
if it.def_id.def_id != self.def_id {
self.check(it.def_id.def_id);
if it.owner_id.def_id != self.def_id {
self.check(it.owner_id.def_id);
intravisit::walk_impl_item(self, it);
}
}
fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
trace!(?it.def_id);
self.check(it.def_id.def_id);
trace!(?it.owner_id);
self.check(it.owner_id.def_id);
intravisit::walk_trait_item(self, it);
}
}
@ -693,6 +701,12 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
tcx.sess.emit_err(UnconstrainedOpaqueType {
span: tcx.def_span(def_id),
name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
what: match tcx.hir().get(scope) {
_ if scope == hir::CRATE_HIR_ID => "module",
Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
_ => "item",
},
});
return tcx.ty_error();
};
@ -764,24 +778,24 @@ fn find_opaque_ty_constraints_for_rpit(
intravisit::walk_expr(self, ex);
}
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
trace!(?it.def_id);
trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
if it.def_id.def_id != self.def_id {
self.check(it.def_id.def_id);
if it.owner_id.def_id != self.def_id {
self.check(it.owner_id.def_id);
intravisit::walk_item(self, it);
}
}
fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
trace!(?it.def_id);
trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
if it.def_id.def_id != self.def_id {
self.check(it.def_id.def_id);
if it.owner_id.def_id != self.def_id {
self.check(it.owner_id.def_id);
intravisit::walk_impl_item(self, it);
}
}
fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
trace!(?it.def_id);
self.check(it.def_id.def_id);
trace!(?it.owner_id);
self.check(it.owner_id.def_id);
intravisit::walk_trait_item(self, it);
}
}

View file

@ -1,7 +1,7 @@
//! Errors emitted by `rustc_hir_analysis`.
use rustc_errors::IntoDiagnostic;
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler};
use rustc_errors::{IntoDiagnostic, MultiSpan};
use rustc_macros::{Diagnostic, LintDiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::{symbol::Ident, Span, Symbol};
@ -143,6 +143,7 @@ pub struct UnconstrainedOpaqueType {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub what: &'static str,
}
pub struct MissingTypeParams {
@ -249,3 +250,33 @@ pub struct ExpectedUsedSymbol {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_const_impl_for_non_const_trait)]
pub struct ConstImplForNonConstTrait {
#[primary_span]
pub trait_ref_span: Span,
pub trait_name: String,
#[suggestion(applicability = "machine-applicable", code = "#[const_trait]")]
pub local_trait_span: Option<Span>,
#[note]
pub marking: (),
#[note(adding)]
pub adding: (),
}
#[derive(Diagnostic)]
#[diag(hir_analysis_const_bound_for_non_const_trait)]
pub struct ConstBoundForNonConstTrait {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_self_in_impl_self)]
pub struct SelfInImplSelf {
#[primary_span]
pub span: MultiSpan,
#[note]
pub note: (),
}

View file

@ -55,10 +55,10 @@ 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.def_id), DefKind::Impl) {
enforce_impl_params_are_constrained(tcx, id.def_id.def_id);
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.def_id.def_id);
check_min_specialization(tcx, id.owner_id.def_id);
}
}
}

View file

@ -381,7 +381,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
error = true;
}
if let hir::IsAsync::Async = sig.header.asyncness {
let span = tcx.def_span(it.def_id);
let span = tcx.def_span(it.owner_id);
struct_span_err!(
tcx.sess,
span,

View file

@ -29,7 +29,7 @@ pub(super) fn infer_predicates<'tcx>(
// Visit all the crates and infer predicates
for id in tcx.hir().items() {
let item_did = id.def_id;
let item_did = id.owner_id;
debug!("InferVisitor::visit_item(item={:?})", item_did);

View file

@ -6,11 +6,11 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
for id in tcx.hir().items() {
// For unit testing: check for a special "rustc_outlives"
// attribute and report an error with various results if found.
if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_outlives) {
let inferred_outlives_of = tcx.inferred_outlives_of(id.def_id);
if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_outlives) {
let inferred_outlives_of = tcx.inferred_outlives_of(id.owner_id);
struct_span_err!(
tcx.sess,
tcx.def_span(id.def_id),
tcx.def_span(id.owner_id),
E0640,
"{:?}",
inferred_outlives_of

View file

@ -6,9 +6,10 @@ pub fn test_variance(tcx: TyCtxt<'_>) {
// For unit testing: check for a special "rustc_variance"
// attribute and report an error with various results if found.
for id in tcx.hir().items() {
if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_variance) {
let variances_of = tcx.variances_of(id.def_id);
struct_span_err!(tcx.sess, tcx.def_span(id.def_id), E0208, "{:?}", variances_of).emit();
if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_variance) {
let variances_of = tcx.variances_of(id.owner_id);
struct_span_err!(tcx.sess, tcx.def_span(id.owner_id), E0208, "{:?}", variances_of)
.emit();
}
}
}

View file

@ -60,6 +60,8 @@ pub struct CastCheck<'tcx> {
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span,
/// whether the cast is made in a const context or not.
pub constness: hir::Constness,
}
/// The kind of pointer and associated metadata (thin, length or vtable) - we
@ -210,9 +212,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span,
constness: hir::Constness,
) -> Result<CastCheck<'tcx>, ErrorGuaranteed> {
let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span);
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span };
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span, constness };
// For better error messages, check for some obviously unsized
// cases now. We do a more thorough check at the end, once
@ -866,7 +869,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
(_, DynStar) | (DynStar, _) => bug!("should be handled by `try_coerce`"),
(_, DynStar) | (DynStar, _) => {
if fcx.tcx.features().dyn_star {
bug!("should be handled by `try_coerce`")
} else {
Err(CastError::IllegalCast)
}
}
}
}

View file

@ -530,24 +530,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
checked_ty: Ty<'tcx>,
hir_id: hir::HirId,
) -> Vec<AssocItem> {
let mut methods =
self.probe_for_return_type(span, probe::Mode::MethodCall, expected, checked_ty, hir_id);
methods.retain(|m| {
self.has_only_self_parameter(m)
&& self
.tcx
// This special internal attribute is used to permit
// "identity-like" conversion methods to be suggested here.
//
// FIXME (#46459 and #46460): ideally
// `std::convert::Into::into` and `std::borrow:ToOwned` would
// also be `#[rustc_conversion_suggestion]`, if not for
// method-probing false-positives and -negatives (respectively).
//
// FIXME? Other potential candidate methods: `as_ref` and
// `as_mut`?
.has_attr(m.def_id, sym::rustc_conversion_suggestion)
});
let methods = self.probe_for_return_type(
span,
probe::Mode::MethodCall,
expected,
checked_ty,
hir_id,
|m| {
self.has_only_self_parameter(m)
&& self
.tcx
// This special internal attribute is used to permit
// "identity-like" conversion methods to be suggested here.
//
// FIXME (#46459 and #46460): ideally
// `std::convert::Into::into` and `std::borrow:ToOwned` would
// also be `#[rustc_conversion_suggestion]`, if not for
// method-probing false-positives and -negatives (respectively).
//
// FIXME? Other potential candidate methods: `as_ref` and
// `as_mut`?
.has_attr(m.def_id, sym::rustc_conversion_suggestion)
},
);
methods
}
@ -714,7 +719,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'tcx>,
checked_ty: Ty<'tcx>,
expected: Ty<'tcx>,
) -> Option<(Span, String, String, Applicability, bool /* verbose */)> {
) -> Option<(
Span,
String,
String,
Applicability,
bool, /* verbose */
bool, /* suggest `&` or `&mut` type annotation */
)> {
let sess = self.sess();
let sp = expr.span;
@ -746,6 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
String::new(),
Applicability::MachineApplicable,
true,
false,
));
}
}
@ -760,6 +773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"b".to_string(),
Applicability::MachineApplicable,
true,
false,
));
}
}
@ -817,6 +831,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg.2,
Applicability::MachineApplicable,
false,
false,
));
}
@ -844,6 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("{prefix}&mut {sugg_expr}"),
Applicability::MachineApplicable,
false,
false,
),
hir::Mutability::Not => (
sp,
@ -851,6 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("{prefix}&{sugg_expr}"),
Applicability::MachineApplicable,
false,
false,
),
});
}
@ -880,6 +897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
String::new(),
Applicability::MachineApplicable,
true,
true
));
}
return None;
@ -893,6 +911,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
String::new(),
Applicability::MachineApplicable,
true,
true,
));
}
}
@ -959,6 +978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
src,
applicability,
true,
false,
));
}
}
@ -999,6 +1019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Applicability::MachineApplicable
},
true,
false,
));
}
@ -1050,6 +1071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
suggestion,
Applicability::MachineApplicable,
true,
false,
));
}
}

View file

@ -1272,7 +1272,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
// Defer other checks until we're done type checking.
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
match cast::CastCheck::new(
self,
e,
t_expr,
t_cast,
t.span,
expr.span,
self.param_env.constness(),
) {
Ok(cast_check) => {
debug!(
"check_expr_cast: deferring cast from {:?} to {:?}: {:?}",

View file

@ -33,16 +33,27 @@ use rustc_span::{self, sym, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
use std::iter;
use std::mem;
use std::ops::ControlFlow;
use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn check_casts(&self) {
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
pub(in super::super) fn check_casts(&mut self) {
// don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors
// when writing to `self.param_env`.
let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut());
debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
for cast in deferred_cast_checks.drain(..) {
let prev_env = self.param_env;
self.param_env = self.param_env.with_constness(cast.constness);
cast.check(self);
self.param_env = prev_env;
}
*self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;
}
pub(in super::super) fn check_transmutes(&self) {

View file

@ -327,7 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
) -> bool {
let expr = expr.peel_blocks();
if let Some((sp, msg, suggestion, applicability, verbose)) =
if let Some((sp, msg, suggestion, applicability, verbose, annotation)) =
self.check_ref(expr, found, expected)
{
if verbose {
@ -335,9 +335,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
err.span_suggestion(sp, &msg, suggestion, applicability);
}
if annotation {
let suggest_annotation = match expr.peel_drop_temps().kind {
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) => "&",
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) => "&mut ",
_ => return true,
};
let mut tuple_indexes = Vec::new();
let mut expr_id = expr.hir_id;
for (parent_id, node) in self.tcx.hir().parent_iter(expr.hir_id) {
match node {
Node::Expr(&Expr { kind: ExprKind::Tup(subs), .. }) => {
tuple_indexes.push(
subs.iter()
.enumerate()
.find(|(_, sub_expr)| sub_expr.hir_id == expr_id)
.unwrap()
.0,
);
expr_id = parent_id;
}
Node::Local(local) => {
if let Some(mut ty) = local.ty {
while let Some(index) = tuple_indexes.pop() {
match ty.kind {
TyKind::Tup(tys) => ty = &tys[index],
_ => return true,
}
}
let annotation_span = ty.span;
err.span_suggestion(
annotation_span.with_hi(annotation_span.lo()),
format!("alternatively, consider changing the type annotation"),
suggest_annotation,
Applicability::MaybeIncorrect,
);
}
break;
}
_ => break,
}
}
}
return true;
} else if self.suggest_else_fn_with_closure(err, expr, found, expected)
{
} else if self.suggest_else_fn_with_closure(err, expr, found, expected) {
return true;
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
&& let ty::FnDef(def_id, ..) = &found.kind()

View file

@ -52,7 +52,7 @@ pub use inherited::{Inherited, InheritedBuilder};
use crate::check::check_fn;
use crate::coercion::DynamicCoerceMany;
use crate::gather_locals::GatherLocalsVisitor;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{struct_span_err, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::Res;
@ -174,7 +174,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
}
}
fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDefId> {
fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDefId> {
&*tcx.typeck(def_id).used_trait_imports
}

View file

@ -252,7 +252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// would result in an error (basically, the same criteria we
/// would use to decide if a method is a plausible fit for
/// ambiguity purposes).
#[instrument(level = "debug", skip(self))]
#[instrument(level = "debug", skip(self, candidate_filter))]
pub fn probe_for_return_type(
&self,
span: Span,
@ -260,6 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return_type: Ty<'tcx>,
self_ty: Ty<'tcx>,
scope_expr_id: hir::HirId,
candidate_filter: impl Fn(&ty::AssocItem) -> bool,
) -> Vec<ty::AssocItem> {
let method_names = self
.probe_op(
@ -271,7 +272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self_ty,
scope_expr_id,
ProbeScope::AllTraits,
|probe_cx| Ok(probe_cx.candidate_method_names()),
|probe_cx| Ok(probe_cx.candidate_method_names(candidate_filter)),
)
.unwrap_or_default();
method_names
@ -966,12 +967,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
fn candidate_method_names(&self) -> Vec<Ident> {
fn candidate_method_names(
&self,
candidate_filter: impl Fn(&ty::AssocItem) -> bool,
) -> Vec<Ident> {
let mut set = FxHashSet::default();
let mut names: Vec<_> = self
.inherent_candidates
.iter()
.chain(&self.extension_candidates)
.filter(|candidate| candidate_filter(&candidate.item))
.filter(|candidate| {
if let Some(return_ty) = self.return_type {
self.matches_return_type(&candidate.item, None, return_ty)
@ -1689,7 +1694,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
pcx.allow_similar_names = true;
pcx.assemble_inherent_candidates();
let method_names = pcx.candidate_method_names();
let method_names = pcx.candidate_method_names(|_| true);
pcx.allow_similar_names = false;
let applicable_close_candidates: Vec<ty::AssocItem> = method_names
.iter()

View file

@ -106,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let report_candidates = |span: Span,
err: &mut Diagnostic,
mut sources: Vec<CandidateSource>,
sources: &mut Vec<CandidateSource>,
sugg_span: Span| {
sources.sort();
sources.dedup();
@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match error {
MethodError::NoMatch(NoMatchData {
static_candidates: static_sources,
static_candidates: mut static_sources,
unsatisfied_predicates,
out_of_scope_traits,
lev_candidate,
@ -422,9 +422,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help(&format!("try with `{}::{}`", ty_str, item_name,));
}
report_candidates(span, &mut err, static_sources, sugg_span);
report_candidates(span, &mut err, &mut static_sources, sugg_span);
} else if static_sources.len() > 1 {
report_candidates(span, &mut err, static_sources, sugg_span);
report_candidates(span, &mut err, &mut static_sources, sugg_span);
}
let mut bound_spans = vec![];
@ -1007,6 +1007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
source,
out_of_scope_traits,
&unsatisfied_predicates,
&static_sources,
unsatisfied_bounds,
);
}
@ -1079,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Some(err);
}
MethodError::Ambiguity(sources) => {
MethodError::Ambiguity(mut sources) => {
let mut err = struct_span_err!(
self.sess(),
item_name.span,
@ -1088,7 +1089,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
err.span_label(item_name.span, format!("multiple `{}` found", item_name));
report_candidates(span, &mut err, sources, sugg_span);
report_candidates(span, &mut err, &mut sources, sugg_span);
err.emit();
}
@ -2015,6 +2016,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Option<ty::Predicate<'tcx>>,
Option<ObligationCause<'tcx>>,
)],
static_candidates: &[CandidateSource],
unsatisfied_bounds: bool,
) {
let mut alt_rcvr_sugg = false;
@ -2128,6 +2130,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(attr) => attr.level.is_stable(),
None => true,
})
.filter(|info| {
// Static candidates are already implemented, and known not to work
// Do not suggest them again
static_candidates.iter().all(|sc| match *sc {
CandidateSource::Trait(def_id) => def_id != info.def_id,
CandidateSource::Impl(def_id) => {
self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
}
})
})
.filter(|info| {
// We approximate the coherence rules to only suggest
// traits that are legal to implement by requiring that

View file

@ -149,19 +149,19 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
dirty_clean_visitor.check_item(id.def_id.def_id);
dirty_clean_visitor.check_item(id.owner_id.def_id);
}
for id in crate_items.trait_items() {
dirty_clean_visitor.check_item(id.def_id.def_id);
dirty_clean_visitor.check_item(id.owner_id.def_id);
}
for id in crate_items.impl_items() {
dirty_clean_visitor.check_item(id.def_id.def_id);
dirty_clean_visitor.check_item(id.owner_id.def_id);
}
for id in crate_items.foreign_items() {
dirty_clean_visitor.check_item(id.def_id.def_id);
dirty_clean_visitor.check_item(id.owner_id.def_id);
}
let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };

View file

@ -16,8 +16,8 @@ use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelating
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
use crate::traits::query::{Fallible, NoSolution};
use crate::traits::TraitEngine;
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use crate::traits::{PredicateObligations, TraitEngine};
use rustc_data_structures::captures::Captures;
use rustc_index::vec::Idx;
use rustc_index::vec::IndexVec;
@ -509,7 +509,7 @@ impl<'tcx> InferCtxt<'tcx> {
for &(a, b) in &query_response.value.opaque_types {
let a = substitute_value(self.tcx, &result_subst, a);
let b = substitute_value(self.tcx, &result_subst, b);
obligations.extend(self.handle_opaque_type(a, b, true, cause, param_env)?.obligations);
obligations.extend(self.at(cause, param_env).eq(a, b)?.obligations);
}
Ok(InferOk { value: result_subst, obligations })
@ -632,7 +632,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// creates query region constraints.
pub fn make_query_region_constraints<'tcx>(
tcx: TyCtxt<'tcx>,
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory)>,
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory<'tcx>)>,
region_constraints: &RegionConstraintData<'tcx>,
) -> QueryRegionConstraints<'tcx> {
let RegionConstraintData { constraints, verifys, givens, member_constraints } =
@ -741,17 +741,11 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
true
}
fn register_opaque_type(
fn register_opaque_type_obligations(
&mut self,
a: Ty<'tcx>,
b: Ty<'tcx>,
a_is_expected: bool,
obligations: PredicateObligations<'tcx>,
) -> Result<(), TypeError<'tcx>> {
self.obligations.extend(
self.infcx
.handle_opaque_type(a, b, a_is_expected, &self.cause, self.param_env)?
.obligations,
);
self.obligations.extend(obligations);
Ok(())
}
}

View file

@ -286,8 +286,8 @@ pub fn suggest_new_region_bound(
) {
debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
let consider = "consider changing the";
let declare = "to declare that the";
let consider = "consider changing";
let declare = "to declare that";
let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name);
let explicit_static =
arg.map(|arg| format!("explicit `'static` bound to the lifetime of {}", arg));
@ -305,6 +305,10 @@ pub fn suggest_new_region_bound(
return;
};
// Get the identity type for this RPIT
let did = item_id.owner_id.to_def_id();
let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did));
if let Some(span) = opaque
.bounds
.iter()
@ -321,7 +325,7 @@ pub fn suggest_new_region_bound(
if let Some(explicit_static) = &explicit_static {
err.span_suggestion_verbose(
span,
&format!("{} `impl Trait`'s {}", consider, explicit_static),
&format!("{consider} `{ty}`'s {explicit_static}"),
&lifetime_name,
Applicability::MaybeIncorrect,
);
@ -351,12 +355,7 @@ pub fn suggest_new_region_bound(
} else {
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
&format!(
"{declare} `impl Trait` {captures}, {explicit}",
declare = declare,
captures = captures,
explicit = explicit,
),
&format!("{declare} `{ty}` {captures}, {explicit}",),
&plus_lt,
Applicability::MaybeIncorrect,
);
@ -367,7 +366,7 @@ pub fn suggest_new_region_bound(
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
&format!(
"{declare} trait object {captures}, {explicit}",
"{declare} the trait object {captures}, {explicit}",
declare = declare,
captures = captures,
explicit = explicit,
@ -384,7 +383,7 @@ pub fn suggest_new_region_bound(
if let Some(explicit_static) = &explicit_static {
err.span_suggestion_verbose(
lt.span,
&format!("{} trait object's {}", consider, explicit_static),
&format!("{} the trait object's {}", consider, explicit_static),
&lifetime_name,
Applicability::MaybeIncorrect,
);

View file

@ -425,7 +425,7 @@ pub enum SubregionOrigin<'tcx> {
static_assert_size!(SubregionOrigin<'_>, 32);
impl<'tcx> SubregionOrigin<'tcx> {
pub fn to_constraint_category(&self) -> ConstraintCategory {
pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
match self {
Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(),
Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span),
@ -1469,7 +1469,12 @@ impl<'tcx> InferCtxt<'tcx> {
* except during the writeback phase.
*/
resolve::fully_resolve(self, value)
let value = resolve::fully_resolve(self, value);
assert!(
value.as_ref().map_or(true, |value| !value.needs_infer()),
"`{value:?}` is not fully resolved"
);
value
}
pub fn replace_bound_vars_with_fresh_vars<T>(

View file

@ -25,7 +25,9 @@ use crate::infer::combine::ConstEquateRelation;
use crate::infer::InferCtxt;
use crate::infer::{ConstVarValue, ConstVariableValue};
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::PredicateObligation;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
@ -91,11 +93,9 @@ pub trait TypeRelatingDelegate<'tcx> {
);
fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
fn register_opaque_type(
fn register_opaque_type_obligations(
&mut self,
a: Ty<'tcx>,
b: Ty<'tcx>,
a_is_expected: bool,
obligations: Vec<PredicateObligation<'tcx>>,
) -> Result<(), TypeError<'tcx>>;
/// Creates a new universe index. Used when instantiating placeholders.
@ -414,7 +414,12 @@ where
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
_ => unreachable!(),
};
self.delegate.register_opaque_type(a, b, true)?;
let cause = ObligationCause::dummy_with_span(self.delegate.span());
let obligations = self
.infcx
.handle_opaque_type(a, b, true, &cause, self.delegate.param_env())?
.obligations;
self.delegate.register_opaque_type_obligations(obligations)?;
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
Ok(a)
}
@ -592,7 +597,7 @@ where
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| {
infcx.super_combine_tys(self, a, b).or_else(|err| {
self.tcx().sess.delay_span_bug(
self.delegate.span(),
"failure to relate an opaque to itself should result in an error later on",

View file

@ -103,7 +103,7 @@ impl<'tcx> InferCtxt<'tcx> {
return Ok(InferOk { value: (), obligations: vec![] });
}
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() {
ty::Opaque(def_id, substs) if def_id.is_local() => {
let def_id = def_id.expect_local();
let origin = match self.defining_use_anchor {
@ -169,13 +169,14 @@ impl<'tcx> InferCtxt<'tcx> {
param_env,
b,
origin,
a_is_expected,
))
}
_ => None,
};
if let Some(res) = process(a, b) {
if let Some(res) = process(a, b, true) {
res
} else if let Some(res) = process(b, a) {
} else if let Some(res) = process(b, a, false) {
res
} else {
let (a, b) = self.resolve_vars_if_possible((a, b));
@ -514,13 +515,14 @@ impl UseKind {
impl<'tcx> InferCtxt<'tcx> {
#[instrument(skip(self), level = "debug")]
pub fn register_hidden_type(
fn register_hidden_type(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>,
origin: hir::OpaqueTyOrigin,
a_is_expected: bool,
) -> InferResult<'tcx, ()> {
let tcx = self.tcx;
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
@ -539,7 +541,8 @@ impl<'tcx> InferCtxt<'tcx> {
origin,
);
if let Some(prev) = prev {
obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations;
obligations =
self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations;
}
let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());

View file

@ -210,7 +210,7 @@ pub trait TypeOutlivesDelegate<'tcx> {
origin: SubregionOrigin<'tcx>,
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
constraint_category: ConstraintCategory,
constraint_category: ConstraintCategory<'tcx>,
);
fn push_verify(
@ -259,7 +259,7 @@ where
origin: infer::SubregionOrigin<'tcx>,
ty: Ty<'tcx>,
region: ty::Region<'tcx>,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
assert!(!ty.has_escaping_bound_vars());
@ -273,7 +273,7 @@ where
origin: infer::SubregionOrigin<'tcx>,
components: &[Component<'tcx>],
region: ty::Region<'tcx>,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
for component in components.iter() {
let origin = origin.clone();
@ -529,7 +529,7 @@ impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'tcx> {
origin: SubregionOrigin<'tcx>,
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
_constraint_category: ConstraintCategory,
_constraint_category: ConstraintCategory<'tcx>,
) {
self.sub_regions(origin, a, b)
}

View file

@ -2,9 +2,7 @@ use super::combine::{CombineFields, RelationDir};
use super::SubregionOrigin;
use crate::infer::combine::ConstEquateRelation;
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::Obligation;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::TyVar;
@ -130,39 +128,18 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
if self.fields.define_opaque_types && did.is_local() =>
{
let mut generalize = |ty, ty_is_expected| {
let var = infcx.next_ty_var_id_in_universe(
TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: self.fields.trace.cause.span,
},
ty::UniverseIndex::ROOT,
);
self.fields.instantiate(ty, RelationDir::SubtypeOf, var, ty_is_expected)?;
Ok(infcx.tcx.mk_ty_var(var))
};
let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) };
let (ga, gb) = match (a.kind(), b.kind()) {
(&ty::Opaque(..), _) => (a, generalize(b, true)?),
(_, &ty::Opaque(..)) => (generalize(a, false)?, b),
_ => unreachable!(),
};
self.fields.obligations.extend(
infcx
.handle_opaque_type(ga, gb, true, &self.fields.trace.cause, self.param_env())
// Don't leak any generalized type variables out of this
// subtyping relation in the case of a type error.
.map_err(|err| {
let (ga, gb) = self.fields.infcx.resolve_vars_if_possible((ga, gb));
if let TypeError::Sorts(sorts) = err && sorts.expected == ga && sorts.found == gb {
TypeError::Sorts(ExpectedFound { expected: a, found: b })
} else {
err
}
})?
.handle_opaque_type(
a,
b,
self.a_is_expected,
&self.fields.trace.cause,
self.param_env(),
)?
.obligations,
);
Ok(ga)
Ok(a)
}
// Optimization of GeneratorWitness relation since we know that all
// free regions are replaced with bound regions during construction.

View file

@ -16,7 +16,6 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_errors::{ErrorGuaranteed, PResult};
use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
use rustc_hir::def_id::StableCrateId;
use rustc_hir::definitions::Definitions;
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore};
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
@ -30,7 +29,7 @@ use rustc_plugin_impl as plugin;
use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
use rustc_resolve::{Resolver, ResolverArenas};
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType};
use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, MetadataLoaderDyn};
use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn};
use rustc_session::output::filename_for_input;
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
@ -135,10 +134,7 @@ mod boxed_resolver {
f((&mut *resolver).as_mut().unwrap())
}
pub fn to_resolver_outputs(
resolver: Rc<RefCell<BoxedResolver>>,
) -> (Definitions, Box<CrateStoreDyn>, ty::ResolverOutputs, ty::ResolverAstLowering)
{
pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ty::ResolverOutputs {
match Rc::try_unwrap(resolver) {
Ok(resolver) => {
let mut resolver = resolver.into_inner();
@ -788,8 +784,7 @@ pub fn create_global_ctxt<'tcx>(
// incr. comp. yet.
dep_graph.assert_ignored();
let (definitions, cstore, resolver_outputs, resolver_for_lowering) =
BoxedResolver::to_resolver_outputs(resolver);
let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver);
let sess = &compiler.session();
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
@ -816,10 +811,7 @@ pub fn create_global_ctxt<'tcx>(
lint_store,
arena,
hir_arena,
definitions,
cstore,
resolver_outputs,
resolver_for_lowering,
krate,
dep_graph,
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
@ -935,7 +927,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
sess.time("misc_checking_3", || {
parallel!(
{
tcx.ensure().privacy_access_levels(());
tcx.ensure().effective_visibilities(());
parallel!(
{

View file

@ -9,7 +9,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
for id in tcx.hir().items() {
let attrs = finder.tcx.hir().attrs(id.hir_id());
if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
finder.decls = Some(id.def_id.def_id);
finder.decls = Some(id.owner_id.def_id);
}
}

View file

@ -57,29 +57,42 @@ pub enum TokenKind {
// Multi-char tokens:
/// "// comment"
LineComment { doc_style: Option<DocStyle> },
/// `/* block comment */`
///
/// Block comments can be recursive, so the sequence like `/* /* */`
/// Block comments can be recursive, so a sequence like `/* /* */`
/// will not be considered terminated and will result in a parsing error.
BlockComment { doc_style: Option<DocStyle>, terminated: bool },
/// Any whitespace characters sequence.
/// Any whitespace character sequence.
Whitespace,
/// "ident" or "continue"
/// At this step keywords are also considered identifiers.
///
/// At this step, keywords are also considered identifiers.
Ident,
/// Like the above, but containing invalid unicode codepoints.
InvalidIdent,
/// "r#ident"
RawIdent,
/// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the
/// An unknown prefix, like `foo#`, `foo'`, `foo"`.
///
/// Note that only the
/// prefix (`foo`) is included in the token, not the separator (which is
/// lexed as its own distinct token). In Rust 2021 and later, reserved
/// prefixes are reported as errors; in earlier editions, they result in a
/// (allowed by default) lint, and are treated as regular identifier
/// tokens.
UnknownPrefix,
/// "12_u8", "1.0e-40", "b"123"". See `LiteralKind` for more details.
/// Examples: `"12_u8"`, `"1.0e-40"`, `b"123`.
///
/// See [LiteralKind] for more details.
Literal { kind: LiteralKind, suffix_start: u32 },
/// "'a"
Lifetime { starts_with_number: bool },

View file

@ -177,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
| hir::ItemKind::Enum(..)
| hir::ItemKind::Struct(..)
| hir::ItemKind::Union(..) => {
self.check_heap_type(cx, it.span, cx.tcx.type_of(it.def_id))
self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id))
}
_ => (),
}
@ -563,7 +563,7 @@ impl MissingDoc {
// It's an option so the crate root can also use this function (it doesn't
// have a `NodeId`).
if def_id != CRATE_DEF_ID {
if !cx.access_levels.is_exported(def_id) {
if !cx.effective_visibilities.is_exported(def_id) {
return;
}
}
@ -606,9 +606,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
match it.kind {
hir::ItemKind::Trait(..) => {
// Issue #11592: traits are always considered exported, even when private.
if cx.tcx.visibility(it.def_id)
if cx.tcx.visibility(it.owner_id)
== ty::Visibility::Restricted(
cx.tcx.parent_module_from_def_id(it.def_id.def_id).to_def_id(),
cx.tcx.parent_module_from_def_id(it.owner_id.def_id).to_def_id(),
)
{
return;
@ -627,15 +627,15 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
_ => return,
};
let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());
let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
self.check_missing_docs_attrs(cx, it.def_id.def_id, article, desc);
self.check_missing_docs_attrs(cx, it.owner_id.def_id, article, desc);
}
fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) {
let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id());
self.check_missing_docs_attrs(cx, trait_item.def_id.def_id, article, desc);
self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, article, desc);
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
@ -662,13 +662,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
}
let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
self.check_missing_docs_attrs(cx, impl_item.def_id.def_id, article, desc);
let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, article, desc);
}
fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) {
let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id());
self.check_missing_docs_attrs(cx, foreign_item.def_id.def_id, article, desc);
let (article, desc) = cx.tcx.article_and_description(foreign_item.owner_id.to_def_id());
self.check_missing_docs_attrs(cx, foreign_item.owner_id.def_id, article, desc);
}
fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) {
@ -721,7 +721,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS])
impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if !cx.access_levels.is_reachable(item.def_id.def_id) {
if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
return;
}
let (def, ty) = match item.kind {
@ -729,21 +729,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.def_id);
let def = cx.tcx.adt_def(item.owner_id);
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemKind::Union(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.def_id);
let def = cx.tcx.adt_def(item.owner_id);
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemKind::Enum(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.def_id);
let def = cx.tcx.adt_def(item.owner_id);
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
_ => return,
@ -752,7 +752,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
return;
}
let param_env = ty::ParamEnv::empty();
if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) {
if ty.is_copy_modulo_regions(cx.tcx, param_env) {
return;
}
if can_type_implement_copy(
@ -814,7 +814,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if !cx.access_levels.is_reachable(item.def_id.def_id) {
if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
return;
}
@ -841,7 +841,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
debug!("{:?}", self.impling_types);
}
if !self.impling_types.as_ref().unwrap().contains(&item.def_id.def_id) {
if !self.impling_types.as_ref().unwrap().contains(&item.owner_id.def_id) {
cx.struct_span_lint(
MISSING_DEBUG_IMPLEMENTATIONS,
item.span,
@ -1226,7 +1226,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
check_no_mangle_on_generic_fn(
no_mangle_attr,
Some(generics),
cx.tcx.hir().get_generics(it.id.def_id.def_id).unwrap(),
cx.tcx.hir().get_generics(it.id.owner_id.def_id).unwrap(),
it.span,
);
}
@ -1385,7 +1385,8 @@ impl UnreachablePub {
exportable: bool,
) {
let mut applicability = Applicability::MachineApplicable;
if cx.tcx.visibility(def_id).is_public() && !cx.access_levels.is_reachable(def_id) {
if cx.tcx.visibility(def_id).is_public() && !cx.effective_visibilities.is_reachable(def_id)
{
if vis_span.from_expansion() {
applicability = Applicability::MaybeIncorrect;
}
@ -1414,11 +1415,11 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind {
return;
}
self.perform_lint(cx, "item", item.def_id.def_id, item.vis_span, true);
self.perform_lint(cx, "item", item.owner_id.def_id, item.vis_span, true);
}
fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) {
self.perform_lint(cx, "item", foreign_item.def_id.def_id, foreign_item.vis_span, true);
self.perform_lint(cx, "item", foreign_item.owner_id.def_id, foreign_item.vis_span, true);
}
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
@ -1428,8 +1429,8 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
// Only lint inherent impl items.
if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() {
self.perform_lint(cx, "item", impl_item.def_id.def_id, impl_item.vis_span, false);
if cx.tcx.associated_item(impl_item.owner_id).trait_item_def_id.is_none() {
self.perform_lint(cx, "item", impl_item.owner_id.def_id, impl_item.vis_span, false);
}
}
}
@ -1638,7 +1639,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
use rustc_middle::ty::PredicateKind::*;
if cx.tcx.features().trivial_bounds {
let predicates = cx.tcx.predicates_of(item.def_id);
let predicates = cx.tcx.predicates_of(item.owner_id);
for &(predicate, span) in predicates.predicates {
let predicate_kind_name = match predicate.kind().skip_binder() {
Trait(..) => "trait",
@ -1881,7 +1882,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
if let hir::ItemKind::Mod(..) = it.kind {
} else {
self.items_nameable = false;
self.boundary = Some(it.def_id);
self.boundary = Some(it.owner_id);
}
return;
}
@ -1898,7 +1899,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
}
fn check_item_post(&mut self, _cx: &LateContext<'_>, it: &hir::Item<'_>) {
if !self.items_nameable && self.boundary == Some(it.def_id) {
if !self.items_nameable && self.boundary == Some(it.owner_id) {
self.items_nameable = true;
}
}
@ -2164,7 +2165,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
use rustc_middle::middle::resolve_lifetime::Region;
let def_id = item.def_id.def_id;
let def_id = item.owner_id.def_id;
if let hir::ItemKind::Struct(_, ref hir_generics)
| hir::ItemKind::Enum(_, ref hir_generics)
| hir::ItemKind::Union(_, ref hir_generics) = item.kind
@ -2743,7 +2744,7 @@ impl ClashingExternDeclarations {
/// Insert a new foreign item into the seen set. If a symbol with the same name already exists
/// for the item, return its HirId without updating the set.
fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<HirId> {
let did = fi.def_id.to_def_id();
let did = fi.owner_id.to_def_id();
let instance = Instance::new(did, ty::List::identity_for_item(tcx, did));
let name = Symbol::intern(tcx.symbol_name(instance).name);
if let Some(&hir_id) = self.seen_decls.get(&name) {
@ -2761,14 +2762,14 @@ impl ClashingExternDeclarations {
/// symbol's name.
fn name_of_extern_decl(tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> SymbolName {
if let Some((overridden_link_name, overridden_link_name_span)) =
tcx.codegen_fn_attrs(fi.def_id).link_name.map(|overridden_link_name| {
tcx.codegen_fn_attrs(fi.owner_id).link_name.map(|overridden_link_name| {
// FIXME: Instead of searching through the attributes again to get span
// information, we could have codegen_fn_attrs also give span information back for
// where the attribute was defined. However, until this is found to be a
// bottleneck, this does just fine.
(
overridden_link_name,
tcx.get_attr(fi.def_id.to_def_id(), sym::link_name).unwrap().span,
tcx.get_attr(fi.owner_id.to_def_id(), sym::link_name).unwrap().span,
)
})
{
@ -2985,10 +2986,10 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
let tcx = cx.tcx;
if let Some(existing_hid) = self.insert(tcx, this_fi) {
let existing_decl_ty = tcx.type_of(tcx.hir().local_def_id(existing_hid));
let this_decl_ty = tcx.type_of(this_fi.def_id);
let this_decl_ty = tcx.type_of(this_fi.owner_id);
debug!(
"ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}",
existing_hid, existing_decl_ty, this_fi.def_id, this_decl_ty
existing_hid, existing_decl_ty, this_fi.owner_id, this_decl_ty
);
// Check that the declarations match.
if !Self::structurally_same_type(

View file

@ -31,7 +31,7 @@ use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_middle::middle::privacy::AccessLevels;
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::middle::stability;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
@ -542,7 +542,7 @@ pub struct LateContext<'tcx> {
pub param_env: ty::ParamEnv<'tcx>,
/// Items accessible from the crate being checked.
pub access_levels: &'tcx AccessLevels,
pub effective_visibilities: &'tcx EffectiveVisibilities,
/// The store of registered lints and the lint levels.
pub lint_store: &'tcx LintStore,

View file

@ -338,14 +338,14 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>(
module_def_id: LocalDefId,
pass: T,
) {
let access_levels = &tcx.privacy_access_levels(());
let effective_visibilities = &tcx.effective_visibilities(());
let context = LateContext {
tcx,
enclosing_body: None,
cached_typeck_results: Cell::new(None),
param_env: ty::ParamEnv::empty(),
access_levels,
effective_visibilities,
lint_store: unerased_lint_store(tcx),
last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id),
generics: None,
@ -386,14 +386,14 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>(
}
fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) {
let access_levels = &tcx.privacy_access_levels(());
let effective_visibilities = &tcx.effective_visibilities(());
let context = LateContext {
tcx,
enclosing_body: None,
cached_typeck_results: Cell::new(None),
param_env: ty::ParamEnv::empty(),
access_levels,
effective_visibilities,
lint_store: unerased_lint_store(tcx),
last_node_with_lint_attrs: hir::CRATE_HIR_ID,
generics: None,

View file

@ -212,7 +212,7 @@ macro_rules! late_lint_mod_passes {
TypeLimits: TypeLimits::new(),
NonSnakeCase: NonSnakeCase,
InvalidNoMangleItems: InvalidNoMangleItems,
// Depends on access levels
// Depends on effective visibilities
UnreachablePub: UnreachablePub,
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
InvalidValue: InvalidValue,

View file

@ -61,7 +61,7 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]);
impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
let hir::ItemKind::OpaqueTy(_) = &item.kind else { return; };
let def_id = item.def_id.def_id.to_def_id();
let def_id = item.owner_id.def_id.to_def_id();
let infcx = &cx.tcx.infer_ctxt().build();
// For every projection predicate in the opaque type's explicit bounds,
// check that the type that we're assigning actually satisfies the bounds

View file

@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
use rustc_middle::ty::PredicateKind::*;
let predicates = cx.tcx.explicit_predicates_of(item.def_id);
let predicates = cx.tcx.explicit_predicates_of(item.owner_id);
for &(predicate, span) in predicates.predicates {
let Trait(trait_predicate) = predicate.kind().skip_binder() else {
continue

View file

@ -11,7 +11,7 @@ use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol, DUMMY_SP};
use rustc_span::{Span, Symbol};
use rustc_target::abi::{Abi, WrappingRange};
use rustc_target::abi::{Integer, TagEncoding, Variants};
use rustc_target::spec::abi::Abi as SpecAbi;
@ -931,7 +931,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match *ty.kind() {
ty::Adt(def, substs) => {
if def.is_box() && matches!(self.mode, CItemKind::Definition) {
if ty.boxed_ty().is_sized(tcx.at(DUMMY_SP), self.cx.param_env) {
if ty.boxed_ty().is_sized(tcx, self.cx.param_env) {
return FfiSafe;
} else {
return FfiUnsafe {
@ -1082,7 +1082,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _)
if {
matches!(self.mode, CItemKind::Definition)
&& ty.is_sized(self.cx.tcx.at(DUMMY_SP), self.cx.param_env)
&& ty.is_sized(self.cx.tcx, self.cx.param_env)
} =>
{
FfiSafe
@ -1360,7 +1360,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind {
let t = cx.tcx.type_of(it.def_id);
let t = cx.tcx.type_of(it.owner_id);
let ty = cx.tcx.erase_regions(t);
let Ok(layout) = cx.layout_of(ty) else { return };
let Variants::Multiple {

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