diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 3a0af04f9eb98..3893875e9a405 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -259,7 +259,6 @@ pub enum ExprPrecedence {
Assign,
AssignOp,
- Box,
AddrOf,
Let,
Unary,
@@ -319,8 +318,7 @@ impl ExprPrecedence {
ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8,
// Unary, prefix
- ExprPrecedence::Box
- | ExprPrecedence::AddrOf
+ ExprPrecedence::AddrOf
// Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`.
// However, this is not exactly right. When `let _ = a` is the LHS of a binop we
// need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 592fc5aa6456f..f4cd10e3b86e9 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -286,10 +286,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span)
} else if generic_args.is_empty() {
// If there are brackets, but not generic arguments, then use the opening bracket
- generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
+ self.tcx
+ .mark_span_for_resize(generic_args.span)
+ .with_hi(generic_args.span.lo() + BytePos(1))
} else {
// Else use an empty span right after the opening bracket.
- generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
+ self.tcx
+ .mark_span_for_resize(generic_args.span)
+ .with_lo(generic_args.span.lo() + BytePos(1))
+ .shrink_to_lo()
};
generic_args.args.insert_many(
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 7c88205da3b9a..cbba1c7b4ad14 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -2075,12 +2075,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Ok(string) => {
if string.starts_with("async ") {
let pos = args_span.lo() + BytePos(6);
- (args_span.with_lo(pos).with_hi(pos), "move ")
+ (
+ self.infcx.tcx.mark_span_for_resize(args_span).with_lo(pos).with_hi(pos),
+ "move ",
+ )
} else if string.starts_with("async|") {
let pos = args_span.lo() + BytePos(5);
- (args_span.with_lo(pos).with_hi(pos), " move")
+ (
+ self.infcx.tcx.mark_span_for_resize(args_span).with_lo(pos).with_hi(pos),
+ " move",
+ )
} else {
- (args_span.shrink_to_lo(), "move ")
+ (self.infcx.tcx.mark_span_for_resize(args_span).shrink_to_lo(), "move ")
}
}
Err(_) => (args_span, "move || "),
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 3662bec0c7636..876d5e6491e95 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -455,7 +455,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
Ok(snippet) if snippet.starts_with('*') => {
err.span_suggestion_verbose(
- span.with_hi(span.lo() + BytePos(1)),
+ self.infcx.tcx.mark_span_for_resize(span).with_hi(span.lo() + BytePos(1)),
"consider removing the dereference here",
String::new(),
Applicability::MaybeIncorrect,
@@ -463,7 +463,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
_ => {
err.span_suggestion_verbose(
- span.shrink_to_lo(),
+ self.infcx.tcx.mark_span_for_resize(span).shrink_to_lo(),
"consider borrowing here",
'&',
Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 905d8c42b28bc..dbf15a3e05fa9 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -255,7 +255,7 @@ fn sccs_info<'cx, 'tcx>(
let var_to_origin = infcx.reg_var_to_origin.borrow();
let mut var_to_origin_sorted = var_to_origin.clone().into_iter().collect::>();
- var_to_origin_sorted.sort_by(|a, b| a.0.cmp(&b.0));
+ var_to_origin_sorted.sort_by_key(|vto| vto.0);
let mut debug_str = "region variables to origins:\n".to_string();
for (reg_var, origin) in var_to_origin_sorted.into_iter() {
debug_str.push_str(&format!("{:?}: {:?}\n", reg_var, origin));
@@ -2216,7 +2216,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// is in the same SCC or something. In that case, find what
// appears to be the most interesting point to report to the
// user via an even more ad-hoc guess.
- categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));
+ categorized_path.sort_by_key(|p| p.category);
debug!("sorted_path={:#?}", categorized_path);
(categorized_path.remove(0), extra_info)
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index ac6697232cb82..ff366cc20db60 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -20,16 +20,16 @@ pub fn expand(
// Allow using `#[alloc_error_handler]` on an item statement
// FIXME - if we get deref patterns, use them to reduce duplication here
- let (item, is_stmt, sig_span) =
+ let (item, is_stmt, sig) =
if let Annotatable::Item(item) = &item
&& let ItemKind::Fn(fn_kind) = &item.kind
{
- (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
+ (item, false, &fn_kind.sig)
} else if let Annotatable::Stmt(stmt) = &item
&& let StmtKind::Item(item) = &stmt.kind
&& let ItemKind::Fn(fn_kind) = &item.kind
{
- (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
+ (item, true, &fn_kind.sig)
} else {
ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
return vec![orig_item];
@@ -39,10 +39,10 @@ pub fn expand(
let span = ecx.with_def_site_ctxt(item.span);
// Generate item statements for the allocator methods.
- let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)];
+ let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig)];
// Generate anonymous constant serving as container for the allocator methods.
- let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
+ let const_ty = ecx.ty(ecx.with_def_site_ctxt(sig.span), TyKind::Tup(ThinVec::new()));
let const_body = ecx.expr_block(ecx.block(span, stmts));
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
let const_item = if is_stmt {
@@ -59,27 +59,31 @@ pub fn expand(
// unsafe fn __rg_oom(size: usize, align: usize) -> ! {
// handler(core::alloc::Layout::from_size_align_unchecked(size, align))
// }
-fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt {
+fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig: &FnSig) -> Stmt {
let usize = cx.path_ident(span, Ident::new(sym::usize, span));
let ty_usize = cx.ty_path(usize);
let size = Ident::from_str_and_span("size", span);
let align = Ident::from_str_and_span("align", span);
+ let sig_span = cx.with_def_site_ctxt(sig.span);
+ let ret_sp = cx.with_def_site_ctxt(sig.decl.output.span());
+
+ // core::alloc::Layout::from_size_align_unchecked(size, align)
let layout_new = cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]);
let layout_new = cx.expr_path(cx.path(span, layout_new));
let layout = cx.expr_call(
- span,
+ cx.with_def_site_ctxt(sig.decl.inputs.get(0).map_or(span, |p| p.span)),
layout_new,
thin_vec![cx.expr_ident(span, size), cx.expr_ident(span, align)],
);
-
- let call = cx.expr_call_ident(sig_span, handler, thin_vec![layout]);
+ let call =
+ cx.expr(ret_sp, ast::ExprKind::Call(cx.expr_ident(span, handler), thin_vec![layout]));
let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never));
let params = thin_vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)];
let decl = cx.fn_decl(params, never);
let header = FnHeader { unsafety: Unsafe::Yes(span), ..FnHeader::default() };
- let sig = FnSig { decl, header, span: span };
+ let sig = FnSig { decl, header, span };
let body = Some(cx.block_expr(call));
let kind = ItemKind::Fn(Box::new(Fn {
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index 2a8dc02849ea7..267d610279e5f 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -138,7 +138,7 @@ fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
}
_ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
};
- struct_span_err!(sess, lit.span, E0777, "expected path to a trait, found literal",)
+ struct_span_err!(sess, lit.span, E0777, "expected path to a trait, found literal")
.span_label(lit.span, "not a trait")
.help(&help_msg)
.emit();
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 8aa744ce93531..8bb143ed3da8d 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1199,7 +1199,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
.and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
.unwrap_or(stem);
- // GCC can have an optional target prefix.
+ // GCC/Clang can have an optional target prefix.
let flavor = if stem == "emcc" {
LinkerFlavor::EmCc
} else if stem == "gcc"
@@ -1207,7 +1207,9 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|| stem == "g++"
|| stem.ends_with("-g++")
|| stem == "clang"
+ || stem.ends_with("-clang")
|| stem == "clang++"
+ || stem.ends_with("-clang++")
{
LinkerFlavor::from_cli(LinkerFlavorCli::Gcc, &sess.target)
} else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index c0f5b3725b36d..9ea58507fd681 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -256,11 +256,17 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
{
let rhs_pos =
span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
- let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
+ let rhs_span = tcx
+ .mark_span_for_resize(span)
+ .with_lo(rhs_pos)
+ .with_hi(rhs_pos);
err.multipart_suggestion(
"consider dereferencing here",
vec![
- (span.shrink_to_lo(), deref.clone()),
+ (
+ tcx.mark_span_for_resize(span).shrink_to_lo(),
+ deref.clone(),
+ ),
(rhs_span, deref),
],
Applicability::MachineApplicable,
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 9ed8ab67431c0..43718b35c8dc8 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -621,6 +621,10 @@ impl Diagnostic {
.map(|(span, snippet)| SubstitutionPart { snippet, span })
.collect::>();
+ if !parts.iter().all(|sub| sub.span.can_be_used_for_suggestions()) {
+ return self;
+ }
+
parts.sort_unstable_by_key(|part| part.span);
assert!(!parts.is_empty());
@@ -711,6 +715,9 @@ impl Diagnostic {
!(sp.is_empty() && suggestion.to_string().is_empty()),
"Span must not be empty and have no suggestion"
);
+ if !sp.can_be_used_for_suggestions() {
+ return self;
+ }
self.push_suggestion(CodeSuggestion {
substitutions: vec![Substitution {
parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
@@ -774,6 +781,9 @@ impl Diagnostic {
!(sp.is_empty() && suggestions.iter().any(|suggestion| suggestion.is_empty())),
"Span must not be empty and have no suggestion"
);
+ if !sp.can_be_used_for_suggestions() {
+ return self;
+ }
let substitutions = suggestions
.into_iter()
@@ -799,12 +809,16 @@ impl Diagnostic {
) -> &mut Self {
let substitutions = suggestions
.into_iter()
- .map(|sugg| {
+ .filter_map(|sugg| {
let mut parts = sugg
.into_iter()
.map(|(span, snippet)| SubstitutionPart { snippet, span })
.collect::>();
+ if !parts.iter().all(|sub| sub.span.can_be_used_for_suggestions()) {
+ return None;
+ }
+
parts.sort_unstable_by_key(|part| part.span);
assert!(!parts.is_empty());
@@ -819,7 +833,7 @@ impl Diagnostic {
"suggestion must not have overlapping parts",
);
- Substitution { parts }
+ Some(Substitution { parts })
})
.collect();
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 1b2e7b7e083b4..aa835c3f53675 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -10,7 +10,7 @@
use Destination::*;
use rustc_span::source_map::SourceMap;
-use rustc_span::{FileLines, SourceFile, Span};
+use rustc_span::{DesugaringKind, FileLines, SourceFile, Span};
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
use crate::styled_buffer::StyledBuffer;
@@ -400,12 +400,13 @@ pub trait Emitter: Translate {
// entries we don't want to print, to make sure the indices being
// printed are contiguous (or omitted if there's only one entry).
let macro_backtrace: Vec<_> = sp.macro_backtrace().collect();
- for (i, trace) in macro_backtrace.iter().rev().enumerate() {
- if trace.def_site.is_dummy() {
- continue;
- }
-
- if always_backtrace && !matches!(trace.kind, ExpnKind::Inlined) {
+ for (i, trace) in macro_backtrace.iter().rev().enumerate().filter(|(_, trace)| {
+ !matches!(
+ trace.kind,
+ ExpnKind::Inlined | ExpnKind::Desugaring(DesugaringKind::Resize)
+ ) && !trace.def_site.is_dummy()
+ }) {
+ if always_backtrace {
new_labels.push((
trace.def_site,
format!(
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index f00a5f24e4545..f4b46b9a131fb 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1673,7 +1673,6 @@ pub struct Expr<'hir> {
impl Expr<'_> {
pub fn precedence(&self) -> ExprPrecedence {
match self.kind {
- ExprKind::Box(_) => ExprPrecedence::Box,
ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
ExprKind::Array(_) => ExprPrecedence::Array,
ExprKind::Call(..) => ExprPrecedence::Call,
@@ -1763,7 +1762,6 @@ impl Expr<'_> {
| ExprKind::Lit(_)
| ExprKind::ConstBlock(..)
| ExprKind::Unary(..)
- | ExprKind::Box(..)
| ExprKind::AddrOf(..)
| ExprKind::Binary(..)
| ExprKind::Yield(..)
@@ -1851,7 +1849,6 @@ impl Expr<'_> {
| ExprKind::InlineAsm(..)
| ExprKind::AssignOp(..)
| ExprKind::ConstBlock(..)
- | ExprKind::Box(..)
| ExprKind::Binary(..)
| ExprKind::Yield(..)
| ExprKind::DropTemps(..)
@@ -1862,8 +1859,7 @@ impl Expr<'_> {
/// To a first-order approximation, is this a pattern?
pub fn is_approximately_pattern(&self) -> bool {
match &self.kind {
- ExprKind::Box(_)
- | ExprKind::Array(_)
+ ExprKind::Array(_)
| ExprKind::Call(..)
| ExprKind::Tup(_)
| ExprKind::Lit(_)
@@ -1910,8 +1906,6 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
#[derive(Debug, HashStable_Generic)]
pub enum ExprKind<'hir> {
- /// A `box x` expression.
- Box(&'hir Expr<'hir>),
/// Allow anonymous constants from an inline `const` block
ConstBlock(AnonConst),
/// An array (e.g., `[a, b, c, d]`).
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index cc0f64017e426..234256ab553c5 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -682,7 +682,6 @@ pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonCo
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) {
visitor.visit_id(expression.hir_id);
match expression.kind {
- ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression),
ExprKind::Array(subexpressions) => {
walk_list!(visitor, visit_expr, subexpressions);
}
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 14dc9d8918000..872fec3954b29 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -557,7 +557,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_opaque(tcx, id);
}
DefKind::ImplTraitPlaceholder => {
- let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id());
+ let parent = tcx.impl_trait_in_trait_parent_fn(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(_)),
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 6e6f8c1533bfe..e1f7a19da071a 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1351,7 +1351,8 @@ fn compare_number_of_method_arguments<'tcx>(
if pos == 0 {
arg.span
} else {
- arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo())
+ tcx.mark_span_for_resize(arg.span)
+ .with_lo(trait_m_sig.decl.inputs[0].span.lo())
}
})
})
@@ -1367,7 +1368,7 @@ fn compare_number_of_method_arguments<'tcx>(
if pos == 0 {
arg.span
} else {
- arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
+ tcx.mark_span_for_resize(arg.span).with_lo(impl_m_sig.decl.inputs[0].span.lo())
}
})
.unwrap_or_else(|| tcx.def_span(impl_m.def_id));
@@ -1464,7 +1465,9 @@ fn compare_synthetic_generics<'tcx>(
// in case there are no generics, take the spot between the function name
// and the opening paren of the argument list
- let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi();
+ let new_generics_span = tcx
+ .mark_span_for_resize(tcx.def_ident_span(impl_def_id)?)
+ .shrink_to_hi();
// in case there are generics, just replace them
let generics_span =
impl_m.generics.span.substitute_dummy(new_generics_span);
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 9acfc1b3d2924..ceca3e634215a 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -220,7 +220,7 @@ fn missing_items_err(
let hi = full_impl_span.hi() - BytePos(1);
// Point at the place right before the closing brace of the relevant `impl` to suggest
// adding the associated item at the end of its body.
- let sugg_sp = full_impl_span.with_lo(hi).with_hi(hi);
+ let sugg_sp = tcx.mark_span_for_resize(full_impl_span).with_lo(hi).with_hi(hi);
// Obtain the level of indentation ending in `sugg_sp`.
let padding =
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 71050864ce0c5..4120ad45f6a6b 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,7 +1,6 @@
use crate::autoderef::Autoderef;
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
-use hir::def::DefKind;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -1548,16 +1547,27 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
&& assoc_item.container == ty::AssocItemContainer::TraitContainer
{
+ // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
+ // strategy, we can't just call `check_associated_item` on the new RPITITs,
+ // because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
+ // That's because we need to check that the bounds of the RPITIT hold using
+ // the special substs that we create during opaque type lowering, otherwise we're
+ // getting a bunch of early bound and free regions mixed up... Haven't looked too
+ // deep into this, though.
for arg in fn_output.walk() {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Alias(ty::Opaque, proj) = ty.kind()
- && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
- && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
+ // RPITITs are always eagerly normalized into opaques, so always look for an
+ // opaque here.
+ && let ty::Alias(ty::Opaque, opaque_ty) = ty.kind()
+ && let Some(opaque_def_id) = opaque_ty.def_id.as_local()
+ && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
+ && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+ && source == fn_def_id
{
- let span = tcx.def_span(proj.def_id);
- let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
+ let span = tcx.def_span(opaque_ty.def_id);
+ let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id);
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
- let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
+ let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs);
let normalized_bound = wfcx.normalize(span, None, bound);
traits::wf::predicate_obligations(
wfcx.infcx,
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 7dce29cc0bbe3..df0258ff7a36c 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -3,7 +3,7 @@ use crate::astconv::AstConv;
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::Span;
@@ -76,18 +76,26 @@ pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> &'_ [(ty::Predicate<'_>, Span)] {
- // If the def_id is about an RPITIT, delegate explicit_item_bounds to the opaque_def_id that
- // generated the synthesized associate type.
- let rpitit_info = if let Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
- tcx.opt_rpitit_info(def_id)
- {
- Some(opaque_def_id)
- } else {
- None
- };
+ match tcx.opt_rpitit_info(def_id) {
+ // RPITIT's bounds are the same as opaque type bounds, but with
+ // a projection self type.
+ Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+ let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
+ let opaque_ty = item.expect_opaque_ty();
+ return opaque_type_bounds(
+ tcx,
+ opaque_def_id,
+ opaque_ty.bounds,
+ tcx.mk_projection(def_id, ty::InternalSubsts::identity_for_item(tcx, def_id)),
+ item.span,
+ );
+ }
+ // These should have been fed!
+ Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
+ None => {}
+ }
- let bounds_def_id = rpitit_info.unwrap_or(def_id);
- let hir_id = tcx.hir().local_def_id_to_hir_id(bounds_def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
match tcx.hir().get(hir_id) {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(bounds, _),
@@ -100,12 +108,12 @@ pub(super) fn explicit_item_bounds(
..
}) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- let item_ty = if *in_trait || rpitit_info.is_some() {
+ let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
tcx.mk_projection(def_id, substs)
} else {
tcx.mk_opaque(def_id, substs)
};
- opaque_type_bounds(tcx, bounds_def_id, bounds, item_ty, *span)
+ opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
}
_ => bug!("item_bounds called on {:?}", def_id),
}
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index cae884ae8fb73..359f3beeaa12b 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -594,7 +594,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
match self.angle_brackets {
AngleBrackets::Missing => {
- let span = self.path_segment.ident.span;
+ let span = self.tcx.mark_span_for_resize(self.path_segment.ident.span);
// insert a suggestion of the form "Y<'a, 'b>"
let sugg = format!("<{}>", suggested_args);
@@ -610,11 +610,23 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
AngleBrackets::Available => {
let (sugg_span, is_first) = if self.num_provided_lifetime_args() == 0 {
- (self.gen_args.span().unwrap().shrink_to_lo(), true)
+ (
+ self.tcx.mark_span_for_resize(self.gen_args.span().unwrap()).shrink_to_lo(),
+ true,
+ )
} else {
let last_lt = &self.gen_args.args[self.num_provided_lifetime_args() - 1];
- (last_lt.span().shrink_to_hi(), false)
+ (self.tcx.mark_span_for_resize(last_lt.span()).shrink_to_hi(), false)
};
+ let path_sp = self.path_segment.ident.span.peel_ctxt();
+ if !self.gen_args.args.iter().all(|arg| {
+ arg.span().can_be_used_for_suggestions()
+ && arg.span().peel_ctxt().ctxt() == path_sp.ctxt()
+ }) || !path_sp.can_be_used_for_suggestions()
+ {
+ // Do not suggest syntax when macros are involved. (#90557)
+ return;
+ }
let has_non_lt_args = self.num_provided_type_or_const_args() != 0;
let has_bindings = !self.gen_args.bindings.is_empty();
@@ -644,7 +656,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
match self.angle_brackets {
AngleBrackets::Missing | AngleBrackets::Implied => {
- let span = self.path_segment.ident.span;
+ let span = self.tcx.mark_span_for_resize(self.path_segment.ident.span);
// insert a suggestion of the form "Y"
let sugg = format!("<{}>", suggested_args);
@@ -658,14 +670,24 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
);
}
AngleBrackets::Available => {
- let gen_args_span = self.gen_args.span().unwrap();
+ let path_sp = self.path_segment.ident.span.peel_ctxt();
+ if !self.gen_args.args.iter().all(|arg| {
+ arg.span().can_be_used_for_suggestions()
+ && arg.span().peel_ctxt().ctxt() == path_sp.ctxt()
+ }) || !path_sp.can_be_used_for_suggestions()
+ {
+ // Do not suggest syntax when macros are involved. (#90557)
+ return;
+ }
+ let gen_args_span = self.tcx.mark_span_for_resize(self.gen_args.span().unwrap());
let sugg_offset =
self.get_lifetime_args_offset() + self.num_provided_type_or_const_args();
let (sugg_span, is_first) = if sugg_offset == 0 {
- (gen_args_span.shrink_to_lo(), true)
+ (self.tcx.mark_span_for_resize(gen_args_span).shrink_to_lo(), true)
} else {
- let arg_span = self.gen_args.args[sugg_offset - 1].span();
+ let arg_span =
+ self.tcx.mark_span_for_resize(self.gen_args.args[sugg_offset - 1].span());
// If we came here then inferred lifetime's spans can only point
// to either the opening bracket or to the space right after.
// Both of these spans have an `hi` lower than or equal to the span
@@ -770,7 +792,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
let sugg = vec![
(self.path_segment.ident.span, format!("{}::{}", snippet, self.path_segment.ident)),
- (span.with_lo(self.path_segment.ident.span.hi()), "".to_owned())
+ (self.tcx.mark_span_for_resize(span).with_lo(self.path_segment.ident.span.hi()), "".to_owned())
];
err.multipart_suggestion(
@@ -953,11 +975,8 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
}
} else if remove_entire_generics {
let span = self
- .path_segment
- .args
- .unwrap()
- .span_ext()
- .unwrap()
+ .tcx
+ .mark_span_for_resize(self.path_segment.args.unwrap().span_ext().unwrap())
.with_lo(self.path_segment.ident.span.hi());
let msg = format!(
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index a8b7699b66750..361e8948e851a 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -112,10 +112,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow {
match t.kind() {
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
- if matches!(
- self.tcx.def_kind(*def_id),
- DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
- ) =>
+ if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
+ {
+ self.visit_opaque(*def_id, substs)
+ }
+ // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
+ // at all for RPITITs.
+ ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+ if self.tcx.is_impl_trait_in_trait(*def_id) =>
{
self.visit_opaque(*def_id, substs)
}
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index d715b03e40ebf..63ea6c904775f 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1366,10 +1366,6 @@ impl<'a> State<'a> {
self.ibox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Expr(expr));
match expr.kind {
- hir::ExprKind::Box(expr) => {
- self.word_space("Box::new");
- self.print_call_post(std::slice::from_ref(expr));
- }
hir::ExprKind::Array(exprs) => {
self.print_expr_vec(exprs);
}
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 6becf4892acb2..ec391ea80f48b 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -2,7 +2,6 @@
use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
-use hir::def::DefKind;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
@@ -715,14 +714,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.subst_iter_copied(self.tcx, substs)
.find_map(|(p, s)| get_future_output(p, s))?,
ty::Error(_) => return None,
- ty::Alias(ty::Projection, proj)
- if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
- {
- self.tcx
- .bound_explicit_item_bounds(proj.def_id)
- .subst_iter_copied(self.tcx, proj.substs)
- .find_map(|(p, s)| get_future_output(p, s))?
- }
+ ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
+ .tcx
+ .bound_explicit_item_bounds(proj.def_id)
+ .subst_iter_copied(self.tcx, proj.substs)
+ .find_map(|(p, s)| get_future_output(p, s))?,
_ => span_bug!(
self.tcx.def_span(expr_def_id),
"async fn generator return type not an inference variable: {ret_ty}"
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index f65f16e317d49..8a7206cecb1ca 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -623,7 +623,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
),
match &args[..] {
- [] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()),
+ [] => (
+ self.tcx
+ .mark_span_for_resize(base.span)
+ .shrink_to_hi()
+ .with_hi(deref.span.hi()),
+ ")".to_string(),
+ ),
[first, ..] => (base.span.between(first.span), ", ".to_string()),
},
]
@@ -747,8 +753,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"use `?` to coerce and return an appropriate `Err`, and wrap the resulting value \
in `Ok` so the expression remains of type `Result`",
vec![
- (expr.span.shrink_to_lo(), "Ok(".to_string()),
- (expr.span.shrink_to_hi(), "?)".to_string()),
+ (self.tcx.mark_span_for_resize(expr.span).shrink_to_lo(), "Ok(".to_string()),
+ (self.tcx.mark_span_for_resize(expr.span).shrink_to_hi(), "?)".to_string()),
],
Applicability::MaybeIncorrect,
);
@@ -819,9 +825,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
return false;
};
- if let Some(indent) =
- self.tcx.sess.source_map().indentation_before(span.shrink_to_lo())
- {
+ if let Some(indent) = self.tcx.sess.source_map().indentation_before(
+ self.tcx.mark_span_for_resize(span).shrink_to_lo(),
+ ) {
// Add a semicolon, except after `}`.
let semicolon =
match self.tcx.sess.source_map().span_to_snippet(span) {
@@ -829,7 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => ";",
};
err.span_suggestions(
- span.shrink_to_hi(),
+ self.tcx.mark_span_for_resize(span).shrink_to_hi(),
"try adding an expression at the end of the block",
return_suggestions
.into_iter()
@@ -907,8 +913,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
vec![
- (expr.span.shrink_to_lo(), format!("{prefix}{variant}{open}")),
- (expr.span.shrink_to_hi(), close.to_owned()),
+ (
+ self.tcx.mark_span_for_resize(expr.span).shrink_to_lo(),
+ format!("{prefix}{variant}{open}"),
+ ),
+ (self.tcx.mark_span_for_resize(expr.span).shrink_to_hi(), close.to_owned()),
]
};
@@ -992,8 +1001,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.multipart_suggestion(
format!("consider calling `{s}::new`"),
vec![
- (expr.span.shrink_to_lo(), format!("{path}::new(")),
- (expr.span.shrink_to_hi(), format!("){unwrap}")),
+ (self.tcx.mark_span_for_resize(expr.span).shrink_to_lo(), format!("{path}::new(")),
+ (self.tcx.mark_span_for_resize(expr.span).shrink_to_hi(), format!("){unwrap}")),
],
Applicability::MaybeIncorrect,
);
@@ -1247,7 +1256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& replace_prefix(&src, "\"", "b\"").is_some()
{
return Some((
- sp.shrink_to_lo(),
+ self.tcx.mark_span_for_resize(sp).shrink_to_lo(),
"consider adding a leading `b`".to_string(),
"b".to_string(),
Applicability::MachineApplicable,
@@ -1444,7 +1453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ if sp == expr.span => {
if let Some(mut steps) = self.deref_steps(checked_ty, expected) {
let mut expr = expr.peel_blocks();
- let mut prefix_span = expr.span.shrink_to_lo();
+ let mut prefix_span = self.tcx.mark_span_for_resize(expr.span).shrink_to_lo();
let mut remove = String::new();
// Try peeling off any existing `&` and `&mut` to reach our target type
@@ -1515,7 +1524,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
} else if let Some(expr) = self.maybe_get_block_expr(expr) {
// prefix should be empty here..
- (expr.span.shrink_to_lo(), "*".to_string())
+ (self.tcx.mark_span_for_resize(expr.span).shrink_to_lo(), "*".to_string())
} else {
(prefix_span, format!("{}{}", prefix, "*".repeat(steps)))
};
@@ -1572,7 +1581,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// `expr` is a literal field for a struct, only suggest if appropriate
if field.is_shorthand {
// This is a field literal
- sugg.push((field.ident.span.shrink_to_lo(), format!("{}: ", field.ident)));
+ sugg.push((
+ self.tcx.mark_span_for_resize(field.ident.span).shrink_to_lo(),
+ format!("{}: ", field.ident),
+ ));
} else {
// Likely a field was meant, but this field wasn't found. Do not suggest anything.
return false;
@@ -1628,16 +1640,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
let close_paren = if expr.precedence().order() < PREC_POSTFIX {
- sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
+ sugg.push((self.tcx.mark_span_for_resize(expr.span).shrink_to_lo(), "(".to_string()));
")"
} else {
""
};
let mut cast_suggestion = sugg.clone();
- cast_suggestion.push((expr.span.shrink_to_hi(), format!("{close_paren} as {expected_ty}")));
+ cast_suggestion.push((
+ self.tcx.mark_span_for_resize(expr.span).shrink_to_hi(),
+ format!("{close_paren} as {expected_ty}"),
+ ));
let mut into_suggestion = sugg.clone();
- into_suggestion.push((expr.span.shrink_to_hi(), format!("{close_paren}.into()")));
+ into_suggestion.push((
+ self.tcx.mark_span_for_resize(expr.span).shrink_to_hi(),
+ format!("{close_paren}.into()"),
+ ));
let mut suffix_suggestion = sugg.clone();
suffix_suggestion.push((
if matches!(
@@ -1691,15 +1709,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"you can convert `{lhs_src}` from `{expected_ty}` to `{checked_ty}`, matching the type of `{src}`",
);
let suggestion = vec![
- (lhs_expr.span.shrink_to_lo(), format!("{checked_ty}::from(")),
- (lhs_expr.span.shrink_to_hi(), ")".to_string()),
+ (
+ self.tcx.mark_span_for_resize(lhs_expr.span).shrink_to_lo(),
+ format!("{checked_ty}::from("),
+ ),
+ (
+ self.tcx.mark_span_for_resize(lhs_expr.span).shrink_to_hi(),
+ ")".to_string(),
+ ),
];
(msg, suggestion)
} else {
let msg = format!("{msg} and panic if the converted value doesn't fit");
let mut suggestion = sugg.clone();
suggestion.push((
- expr.span.shrink_to_hi(),
+ self.tcx.mark_span_for_resize(expr.span).shrink_to_hi(),
format!("{close_paren}.try_into().unwrap()"),
));
(msg, suggestion)
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index afef331ec1d93..b2a01ad44a8e5 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -284,7 +284,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;
match expr.kind {
- ExprKind::Box(subexpr) => self.check_expr_box(subexpr, expected),
ExprKind::Lit(ref lit) => self.check_lit(&lit, expected),
ExprKind::Binary(op, lhs, rhs) => self.check_binop(expr, op, lhs, rhs, expected),
ExprKind::Assign(lhs, rhs, span) => {
@@ -359,16 +358,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- fn check_expr_box(&self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>) -> Ty<'tcx> {
- let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| match ty.kind() {
- ty::Adt(def, _) if def.is_box() => Expectation::rvalue_hint(self, ty.boxed_ty()),
- _ => NoExpectation,
- });
- let referent_ty = self.check_expr_with_expectation(expr, expected_inner);
- self.require_type_is_sized(referent_ty, expr.span, traits::SizedBoxType);
- self.tcx.mk_box(referent_ty)
- }
-
fn check_expr_unary(
&self,
unop: hir::UnOp,
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index b9a058d6bba2c..9aa6c7f103f87 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -356,10 +356,6 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.walk_captures(closure);
}
- hir::ExprKind::Box(ref base) => {
- self.consume_expr(base);
- }
-
hir::ExprKind::Yield(value, _) => {
self.consume_expr(value);
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 7064ff6538487..33663c4e7dcbe 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -31,7 +31,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, IsSuggestable, Ty};
use rustc_session::Session;
use rustc_span::symbol::{kw, Ident};
-use rustc_span::{self, sym, Span};
+use rustc_span::{self, sym, ExpnKind, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
use std::iter;
@@ -496,7 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ExprKind::MethodCall(path_segment, _, _, span) => {
let ident_span = path_segment.ident.span;
let ident_span = if let Some(args) = path_segment.args {
- ident_span.with_hi(args.span_ext.hi())
+ self.tcx.mark_span_for_resize(ident_span).with_hi(args.span_ext.hi())
} else {
ident_span
};
@@ -706,8 +706,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.multipart_suggestion_verbose(
"wrap these arguments in parentheses to construct a tuple",
vec![
- (lo.shrink_to_lo(), "(".to_string()),
- (hi.shrink_to_hi(), ")".to_string()),
+ (tcx.mark_span_for_resize(*lo).shrink_to_lo(), "(".to_string()),
+ (tcx.mark_span_for_resize(*hi).shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable,
);
@@ -939,12 +939,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut span = provided_span;
if span.can_be_used_for_suggestions() {
if arg_idx.index() > 0
- && let Some((_, prev)) = provided_arg_tys
- .get(ProvidedIdx::from_usize(arg_idx.index() - 1)
- ) {
- // Include previous comma
- span = prev.shrink_to_hi().to(span);
- }
+ && let Some((_, prev)) = provided_arg_tys
+ .get(ProvidedIdx::from_usize(arg_idx.index() - 1))
+ {
+ // Include previous comma
+ span = self.tcx.mark_span_for_resize(*prev).shrink_to_hi().to(self.tcx.mark_span_for_resize(span));
+ }
suggestions.push((span, String::new()));
suggestion_text = match suggestion_text {
@@ -1186,6 +1186,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Call out where the function is defined
self.label_fn_like(&mut err, fn_def_id, callee_ty, None, is_method);
+ if !suggestions.iter().all(|(sp, _)| {
+ sp.macro_backtrace().all(|data| !matches!(data.kind, ExpnKind::Macro(..)))
+ }) {
+ // We don't want to provide structured suggestions if macros are involved at all.
+ err.emit();
+ return;
+ }
// And add a suggestion block for all of the parameters
let suggestion_text = match suggestion_text {
SuggestionText::None => None,
@@ -1208,7 +1215,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let source_map = self.sess().source_map();
let (mut suggestion, suggestion_span) =
if let Some(call_span) = full_call_span.find_ancestor_inside(error_span) {
- ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
+ (
+ "(".to_string(),
+ tcx.mark_span_for_resize(call_span)
+ .shrink_to_hi()
+ .to(tcx.mark_span_for_resize(error_span).shrink_to_hi()),
+ )
} else {
(
format!(
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index 7c0402b1c7fb8..1eeb7d984ee04 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -190,7 +190,6 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
//
// Some of these may be interesting in the future
ExprKind::Path(..)
- | ExprKind::Box(..)
| ExprKind::ConstBlock(..)
| ExprKind::Array(..)
| ExprKind::Call(..)
@@ -478,7 +477,6 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
| ExprKind::AssignOp(..)
| ExprKind::Binary(..)
| ExprKind::Block(..)
- | ExprKind::Box(..)
| ExprKind::Cast(..)
| ExprKind::Closure { .. }
| ExprKind::ConstBlock(..)
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 4d3969d28aa2d..9a8d7ca9e3382 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -382,7 +382,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
| hir::ExprKind::Struct(..)
| hir::ExprKind::Repeat(..)
| hir::ExprKind::InlineAsm(..)
- | hir::ExprKind::Box(..)
| hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
}
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ac4986a577c6d..de1a2e6a577bf 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -359,10 +359,12 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option> {
let (def_id, substs) = match *ty.kind() {
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
- if matches!(
- self.tcx.def_kind(def_id),
- DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
- ) =>
+ if matches!(self.tcx.def_kind(def_id), DefKind::OpaqueTy) =>
+ {
+ (def_id, substs)
+ }
+ ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+ if self.tcx.is_impl_trait_in_trait(def_id) =>
{
(def_id, substs)
}
@@ -1757,8 +1759,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
)
}
(true, ty::Alias(ty::Projection, proj))
- if self.tcx.def_kind(proj.def_id)
- == DefKind::ImplTraitPlaceholder =>
+ if self.tcx.is_impl_trait_in_trait(proj.def_id) =>
{
let sm = self.tcx.sess.source_map();
let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index b33729d0be5c9..bc1c7e9b33b21 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -1,7 +1,7 @@
use super::TypeErrCtxt;
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
-use rustc_hir::{self as hir, def::DefKind};
+use rustc_hir as hir;
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::print::Printer;
@@ -75,7 +75,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
diag.note("an associated type was expected, but a different one was found");
}
(ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
- if tcx.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
+ if !tcx.is_impl_trait_in_trait(proj.def_id) =>
{
let p_def_id = tcx
.generics_of(body_owner_def_id)
@@ -125,7 +125,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
matched_end_of_args = args_span.is_some();
matching_span = args_span
.or_else(|| Some(end_of_trait))
- .map(|span| span.shrink_to_hi());
+ .map(|span| self.tcx.mark_span_for_resize(span).shrink_to_hi());
break;
}
}
@@ -222,7 +222,7 @@ impl Trait for X {
diag.span_label(p_span, "this type parameter");
}
}
- (ty::Alias(ty::Projection, proj_ty), _) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
+ (ty::Alias(ty::Projection, proj_ty), _) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
self.expected_projection(
diag,
proj_ty,
@@ -231,7 +231,7 @@ impl Trait for X {
cause.code(),
);
}
- (_, ty::Alias(ty::Projection, proj_ty)) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
+ (_, ty::Alias(ty::Projection, proj_ty)) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
let msg = format!(
"consider constraining the associated type `{}` to `{}`",
values.found, values.expected,
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index ed4bc594d1a54..49f823a47b83d 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -3,7 +3,6 @@ use super::{DefineOpaqueTypes, InferResult};
use crate::errors::OpaqueHiddenTypeDiag;
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
use crate::traits;
-use hir::def::DefKind;
use hir::def_id::{DefId, LocalDefId};
use hir::OpaqueTyOrigin;
use rustc_data_structures::sync::Lrc;
@@ -478,9 +477,7 @@ where
}
}
- ty::Alias(ty::Projection, proj)
- if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
- {
+ ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => {
// Skip lifetime parameters that are not captures.
let variances = self.tcx.variances_of(proj.def_id);
@@ -559,8 +556,7 @@ impl<'tcx> InferCtxt<'tcx> {
// FIXME(RPITIT): Don't replace RPITITs with inference vars.
ty::Alias(ty::Projection, projection_ty)
if !projection_ty.has_escaping_bound_vars()
- && tcx.def_kind(projection_ty.def_id)
- != DefKind::ImplTraitPlaceholder =>
+ && !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
{
self.infer_projection(
param_env,
diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs
index 3045fc1a4761e..8bd436ff7a9d9 100644
--- a/compiler/rustc_lint/src/methods.rs
+++ b/compiler/rustc_lint/src/methods.rs
@@ -36,7 +36,7 @@ declare_lint_pass!(TemporaryCStringAsPtr => [TEMPORARY_CSTRING_AS_PTR]);
fn in_macro(span: Span) -> bool {
if span.from_expansion() {
- !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..))
+ !matches!(span.peel_ctxt().ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..))
} else {
false
}
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 9649ce2c5a771..c778574b2c57b 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1028,7 +1028,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
| DefKind::InlineConst => true,
DefKind::ImplTraitPlaceholder => {
- let parent_def_id = tcx.impl_trait_in_trait_parent(def_id.to_def_id());
+ let parent_def_id = tcx.impl_trait_in_trait_parent_fn(def_id.to_def_id());
let assoc_item = tcx.associated_item(parent_def_id);
match assoc_item.container {
// Always encode an RPIT in an impl fn, since it always has a body
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index c61de97d53271..d25dc4c7e0161 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -466,7 +466,7 @@ pub fn struct_lint_level(
/// This is used to test whether a lint should not even begin to figure out whether it should
/// be reported on the current node.
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
- let expn_data = span.ctxt().outer_expn_data();
+ let expn_data = span.peel_ctxt().ctxt().outer_expn_data();
match expn_data.kind {
ExpnKind::Inlined
| ExpnKind::Root
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 2cd791574417a..c8860cc55f6b7 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -191,6 +191,7 @@ rustc_queries! {
{
desc { "determine whether the opaque is a type-alias impl trait" }
separate_provide_extern
+ feedable
}
query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 6231dd9b6f54a..fb3e9cb126317 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -305,8 +305,6 @@ pub enum ObligationCauseCode<'tcx> {
SizedReturnType,
/// Yield type must be `Sized`.
SizedYieldType,
- /// Box expression result type must be `Sized`.
- SizedBoxType,
/// Inline asm operand type must be `Sized`.
InlineAsmSized,
/// `[expr; N]` requires `type_of(expr): Copy`.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 04d7de531c26b..e23c0f07e6cff 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2500,6 +2500,17 @@ impl<'tcx> TyCtxt<'tcx> {
.hygienic_eq(def_name.span.ctxt(), self.expn_that_defined(def_parent_def_id))
}
+ /// This returns a copy of `span` that has a `DesugaringKind::Resize` mark reason. This mark is
+ /// used to identify `Span`s that have been modified, while also keeping a link to the original
+ /// `Span` before it was changed. This is used today only to be able to identify `Span`s coming
+ /// from a proc-macro even when it was modified, to avoid giving spurious suggestions when the
+ /// `Span` points at an attribute and not user code.
+ pub fn mark_span_for_resize(self, span: Span) -> Span {
+ self.with_stable_hashing_context(|hcx| {
+ span.mark_with_reason(None, rustc_span::DesugaringKind::Resize, span.edition(), hcx)
+ })
+ }
+
pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident {
ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope));
ident
@@ -2552,12 +2563,18 @@ impl<'tcx> TyCtxt<'tcx> {
matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
}
- pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId {
- while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
- debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
- def_id = self.parent(def_id);
+ pub fn impl_trait_in_trait_parent_fn(self, mut def_id: DefId) -> DefId {
+ match self.opt_rpitit_info(def_id) {
+ Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
+ | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id,
+ None => {
+ while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
+ debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
+ def_id = self.parent(def_id);
+ }
+ def_id
+ }
}
- def_id
}
pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
@@ -2572,6 +2589,10 @@ impl<'tcx> TyCtxt<'tcx> {
let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
+ if self.lower_impl_trait_in_trait_to_assoc_ty() {
+ return !self.associated_items_for_impl_trait_in_trait(trait_item_def_id).is_empty();
+ }
+
// FIXME(RPITIT): This does a somewhat manual walk through the signature
// of the trait fn to look for any RPITITs, but that's kinda doing a lot
// of work. We can probably remove this when we refactor RPITITs to be
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index b3139d23d36e3..fffdbfc9660bb 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -728,7 +728,7 @@ pub trait PrettyPrinter<'tcx>:
}
ty::Alias(ty::Projection, ref data) => {
if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
- && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
+ && self.tcx().is_impl_trait_in_trait(data.def_id)
{
return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
} else {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 52d114bae3007..4c606b939b25e 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1288,7 +1288,7 @@ impl<'tcx> AliasTy<'tcx> {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
DefKind::ImplTraitPlaceholder => {
- tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
+ tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id))
}
kind => bug!("expected a projection AliasTy; found {kind:?}"),
}
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 9086412c09a1c..cecb8a61aa2f4 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -780,7 +780,6 @@ impl<'tcx> Cx<'tcx> {
hir::ExprKind::DropTemps(ref source) => {
ExprKind::Use { source: self.mirror_expr(source) }
}
- hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr(value) },
hir::ExprKind::Array(ref fields) => {
ExprKind::Array { fields: self.mirror_exprs(fields) }
}
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 3e0d53029ef99..47e032758f23d 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -300,7 +300,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
record_variants!(
(self, e, e.kind, Id::Node(e.hir_id), hir, Expr, ExprKind),
[
- Box, ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type,
+ ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type,
DropTemps, Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index,
Path, AddrOf, Break, Continue, Ret, InlineAsm, Struct, Repeat, Yield, Err
]
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index db9d0dcc30053..36324e6f8da4a 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -473,7 +473,6 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
| hir::ExprKind::Struct(..)
| hir::ExprKind::Repeat(..)
| hir::ExprKind::InlineAsm(..)
- | hir::ExprKind::Box(..)
| hir::ExprKind::Type(..)
| hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
@@ -1059,8 +1058,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_expr(&l, r_succ)
}
- hir::ExprKind::Box(ref e)
- | hir::ExprKind::AddrOf(_, _, ref e)
+ hir::ExprKind::AddrOf(_, _, ref e)
| hir::ExprKind::Cast(ref e, _)
| hir::ExprKind::Type(ref e, _)
| hir::ExprKind::DropTemps(ref e)
@@ -1425,7 +1423,6 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
| hir::ExprKind::Closure { .. }
| hir::ExprKind::Path(_)
| hir::ExprKind::Yield(..)
- | hir::ExprKind::Box(..)
| hir::ExprKind::Type(..)
| hir::ExprKind::Err(_) => {}
}
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index c5b5cf7f5a963..f07a64c7c3ca2 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -179,8 +179,7 @@ enum ItemKind {
impl<'tcx> CheckInlineAssembly<'tcx> {
fn check_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, span: Span) {
match expr.kind {
- ExprKind::Box(..)
- | ExprKind::ConstBlock(..)
+ ExprKind::ConstBlock(..)
| ExprKind::Array(..)
| ExprKind::Call(..)
| ExprKind::MethodCall(..)
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index ef7c68c1a335a..cd67644589846 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -132,7 +132,7 @@ where
projection.trait_ref_and_own_substs(tcx)
} else {
// HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
- let def_id = tcx.impl_trait_in_trait_parent(projection.def_id);
+ let def_id = tcx.impl_trait_in_trait_parent_fn(projection.def_id);
let trait_generics = tcx.generics_of(def_id);
(
tcx.mk_trait_ref(def_id, projection.substs.truncate_to(tcx, trait_generics)),
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 44a3d4e628ebc..5673fae9e1fdb 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1437,6 +1437,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
suggestion: Option,
span: Span,
) -> bool {
+ if !span.can_be_used_for_suggestions() {
+ return false;
+ }
let suggestion = match suggestion {
None => return false,
// We shouldn't suggest underscore.
@@ -1444,7 +1447,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(suggestion) => suggestion,
};
if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
- if span.overlaps(def_span) {
+ if span.overlaps(def_span) || !def_span.can_be_used_for_suggestions() {
// Don't suggest typo suggestion for itself like in the following:
// error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
// --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index df7681dc4267b..13eb3f99dc047 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -28,7 +28,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, Span};
+use rustc_span::{BytePos, ExpnKind, Span};
use std::iter;
use std::ops::Deref;
@@ -212,7 +212,32 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
} else {
let item_span = path.last().unwrap().ident.span;
- let (mod_prefix, mod_str, suggestion) = if path.len() == 1 {
+ let sp = item_span.peel_ctxt();
+ let ctxt_kind = sp.ctxt().outer_expn_data().kind;
+ let (mod_prefix, mod_str, name, mod_label, suggestion) =
+ if let ExpnKind::Macro(MacroKind::Attr | MacroKind::Bang, name) = ctxt_kind
+ && sp.parent_callsite().map(|p| (p.lo(), p.hi())) == Some((sp.lo(), sp.hi()))
+ {
+ // This span comes from a proc macro and it doesn't point at user code.
+ (
+ String::new(),
+ format!("the expanded code of procedural macro `{name}`"),
+ format!("`{path_str}` "),
+ format!("expanded code of this procedural macro"),
+ None,
+ )
+ } else if let ExpnKind::Macro(MacroKind::Derive, name) = ctxt_kind
+ && sp.parent_callsite().map(|p| (p.lo(), p.hi())) == Some((sp.lo(), sp.hi()))
+ {
+ // This span comes from a `derive` macro and it doesn't point at user code.
+ (
+ String::new(),
+ format!("the expanded code of `derive` macro `{name}`"),
+ format!("`{path_str}` "),
+ format!("expanded code of this `derive` macro"),
+ None,
+ )
+ } else if path.len() == 1 {
debug!(?self.diagnostic_metadata.current_impl_items);
debug!(?self.diagnostic_metadata.current_function);
let suggestion = if self.current_trait_ref.is_none()
@@ -246,18 +271,22 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
} else {
None
};
- (String::new(), "this scope".to_string(), suggestion)
+ let s = "this scope".to_string();
+ (String::new(), s.clone(), String::new(), s, suggestion)
} else if path.len() == 2 && path[0].ident.name == kw::PathRoot {
if self.r.tcx.sess.edition() > Edition::Edition2015 {
// In edition 2018 onwards, the `::foo` syntax may only pull from the extern prelude
// which overrides all other expectations of item type
expected = "crate";
- (String::new(), "the list of imported crates".to_string(), None)
+ let s = "the list of imported crates".to_string();
+ (String::new(), s.clone(), String::new(), s, None)
} else {
- (String::new(), "the crate root".to_string(), None)
+ let s = "the crate root".to_string();
+ (String::new(), s.clone(), String::new(), s, None)
}
} else if path.len() == 2 && path[0].ident.name == kw::Crate {
- (String::new(), "the crate root".to_string(), None)
+ let s = "the crate root".to_string();
+ (String::new(), s.clone(), String::new(), s, None)
} else {
let mod_path = &path[..path.len() - 1];
let mod_prefix = match self.resolve_path(mod_path, Some(TypeNS), None) {
@@ -265,7 +294,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
_ => None,
}
.map_or_else(String::new, |res| format!("{} ", res.descr()));
- (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path)), None)
+ let s = format!("`{}`", Segment::names_to_string(mod_path));
+ (mod_prefix, s.clone(), String::new(), s, None)
};
let (fallback_label, suggestion) = if path_str == "async"
@@ -289,7 +319,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
} else {
suggestion
};
- (format!("not found in {mod_str}"), override_suggestion)
+ (format!("{name}not found in {mod_label}"), override_suggestion)
};
BaseError {
@@ -454,6 +484,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
res: Option,
base_error: &BaseError,
) -> (bool, Vec) {
+ if !span.can_be_used_for_suggestions() {
+ // If the span comes from a proc-macro, we don't want to provide suggestions for
+ // importing and using types. We do make it harder on the proc-macro author, but at
+ // least we don't mislead end-users.
+ return (false, vec![]);
+ }
// Try to lookup name in more relaxed fashion for better error reporting.
let ident = path.last().unwrap().ident;
let is_expected = &|res| source.is_expected(res);
@@ -2150,7 +2186,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
| (Some(Item { kind, .. }), false, _) => {
// Likely missing type parameter.
if let Some(generics) = kind.generics() {
- if span.overlaps(generics.span) {
+ if span.overlaps(generics.span)
+ || !generics.span.can_be_used_for_suggestions()
+ {
// Avoid the following:
// error[E0405]: cannot find trait `A` in this scope
// --> $DIR/typo-suggestion-named-underscore.rs:CC:LL
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 9f22e9776d4f6..34b4650010074 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -181,7 +181,7 @@ impl LocalExpnId {
}
pub fn fresh_empty() -> LocalExpnId {
- HygieneData::with(|data| {
+ HygieneData::with_mut(|data| {
let expn_id = data.local_expn_data.push(None);
let _eid = data.local_expn_hashes.push(ExpnHash(Fingerprint::ZERO));
debug_assert_eq!(expn_id, _eid);
@@ -192,7 +192,7 @@ impl LocalExpnId {
pub fn fresh(mut expn_data: ExpnData, ctx: impl HashStableContext) -> LocalExpnId {
debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
let expn_hash = update_disambiguator(&mut expn_data, ctx);
- HygieneData::with(|data| {
+ HygieneData::with_mut(|data| {
let expn_id = data.local_expn_data.push(Some(expn_data));
let _eid = data.local_expn_hashes.push(expn_hash);
debug_assert_eq!(expn_id, _eid);
@@ -221,7 +221,7 @@ impl LocalExpnId {
pub fn set_expn_data(self, mut expn_data: ExpnData, ctx: impl HashStableContext) {
debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
let expn_hash = update_disambiguator(&mut expn_data, ctx);
- HygieneData::with(|data| {
+ HygieneData::with_mut(|data| {
let old_expn_data = &mut data.local_expn_data[self];
assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID");
*old_expn_data = Some(expn_data);
@@ -383,10 +383,14 @@ impl HygieneData {
}
}
- pub fn with T>(f: F) -> T {
+ pub fn with_mut T>(f: F) -> T {
with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow_mut()))
}
+ pub fn with T>(f: F) -> T {
+ with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow()))
+ }
+
#[inline]
fn local_expn_hash(&self, expn_id: LocalExpnId) -> ExpnHash {
self.local_expn_hashes[expn_id]
@@ -595,7 +599,7 @@ impl HygieneData {
}
pub fn clear_syntax_context_map() {
- HygieneData::with(|data| data.syntax_context_map = FxHashMap::default());
+ HygieneData::with_mut(|data| data.syntax_context_map = FxHashMap::default());
}
pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
@@ -619,7 +623,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb
let range_to_update = len - to_update..len;
let names: Vec<_> =
range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect();
- HygieneData::with(|data| {
+ HygieneData::with_mut(|data| {
range_to_update.zip(names).for_each(|(idx, name)| {
data.syntax_context_data[idx].dollar_crate_name = name;
})
@@ -683,7 +687,7 @@ impl SyntaxContext {
/// Extend a syntax context with a given expansion and transparency.
pub(crate) fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
- HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
+ HygieneData::with_mut(|data| data.apply_mark(self, expn_id, transparency))
}
/// Pulls a single mark off of the syntax context. This effectively moves the
@@ -802,7 +806,7 @@ impl SyntaxContext {
expn_id: ExpnId,
glob_span: Span,
) -> Option