diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 56d4f53f9eea4..14e04774788ef 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2961,6 +2961,7 @@ impl Item {
| ItemKind::GlobalAsm(_)
| ItemKind::MacCall(_)
| ItemKind::Delegation(_)
+ | ItemKind::DelegationMac(_)
| ItemKind::MacroDef(_) => None,
ItemKind::Static(_) => None,
ItemKind::Const(i) => Some(&i.generics),
@@ -3123,8 +3124,16 @@ pub struct Delegation {
/// Path resolution id.
pub id: NodeId,
pub qself: Option
>,
- pub rename: Option,
pub path: Path,
+ pub rename: Option,
+ pub body: Option>,
+}
+
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct DelegationMac {
+ pub qself: Option
>,
+ pub prefix: Path,
+ pub suffixes: ThinVec<(Ident, Option)>,
pub body: Option>,
}
@@ -3243,10 +3252,13 @@ pub enum ItemKind {
/// A macro definition.
MacroDef(MacroDef),
- /// A delegation item (`reuse`).
+ /// A single delegation item (`reuse`).
///
/// E.g. `reuse ::name { target_expr_template }`.
Delegation(Box),
+ /// A list delegation item (`reuse prefix::{a, b, c}`).
+ /// Treated similarly to a macro call and expanded early.
+ DelegationMac(Box),
}
impl ItemKind {
@@ -3256,7 +3268,7 @@ impl ItemKind {
match self {
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
- | Delegation(..) => "a",
+ | Delegation(..) | DelegationMac(..) => "a",
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
}
}
@@ -3281,6 +3293,7 @@ impl ItemKind {
ItemKind::MacroDef(..) => "macro definition",
ItemKind::Impl { .. } => "implementation",
ItemKind::Delegation(..) => "delegated function",
+ ItemKind::DelegationMac(..) => "delegation",
}
}
@@ -3324,6 +3337,8 @@ pub enum AssocItemKind {
MacCall(P),
/// An associated delegation item.
Delegation(Box),
+ /// An associated delegation item list.
+ DelegationMac(Box),
}
impl AssocItemKind {
@@ -3332,7 +3347,9 @@ impl AssocItemKind {
Self::Const(box ConstItem { defaultness, .. })
| Self::Fn(box Fn { defaultness, .. })
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
- Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final,
+ Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => {
+ Defaultness::Final
+ }
}
}
}
@@ -3345,6 +3362,7 @@ impl From for ItemKind {
AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
+ AssocItemKind::DelegationMac(delegation) => ItemKind::DelegationMac(delegation),
}
}
}
@@ -3359,6 +3377,7 @@ impl TryFrom for AssocItemKind {
ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
+ ItemKind::DelegationMac(d) => AssocItemKind::DelegationMac(d),
_ => return Err(item_kind),
})
}
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 5c4162295bbc1..1cfb8972a6280 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1170,6 +1170,19 @@ impl NoopVisitItemKind for ItemKind {
vis.visit_block(body);
}
}
+ ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+ vis.visit_qself(qself);
+ vis.visit_path(prefix);
+ for (ident, rename) in suffixes {
+ vis.visit_ident(ident);
+ if let Some(rename) = rename {
+ vis.visit_ident(rename);
+ }
+ }
+ if let Some(body) = body {
+ vis.visit_block(body);
+ }
+ }
}
}
}
@@ -1213,6 +1226,19 @@ impl NoopVisitItemKind for AssocItemKind {
visitor.visit_block(body);
}
}
+ AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+ visitor.visit_qself(qself);
+ visitor.visit_path(prefix);
+ for (ident, rename) in suffixes {
+ visitor.visit_ident(ident);
+ if let Some(rename) = rename {
+ visitor.visit_ident(rename);
+ }
+ }
+ if let Some(body) = body {
+ visitor.visit_block(body);
+ }
+ }
}
}
}
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index d36193ef7b0ab..7794edc350519 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -403,6 +403,19 @@ impl WalkItemKind for ItemKind {
visit_opt!(visitor, visit_ident, *rename);
visit_opt!(visitor, visit_block, body);
}
+ ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+ if let Some(qself) = qself {
+ try_visit!(visitor.visit_ty(&qself.ty));
+ }
+ try_visit!(visitor.visit_path(prefix, item.id));
+ for (ident, rename) in suffixes {
+ visitor.visit_ident(*ident);
+ if let Some(rename) = rename {
+ visitor.visit_ident(*rename);
+ }
+ }
+ visit_opt!(visitor, visit_block, body);
+ }
}
V::Result::output()
}
@@ -815,6 +828,19 @@ impl WalkItemKind for AssocItemKind {
visit_opt!(visitor, visit_ident, *rename);
visit_opt!(visitor, visit_block, body);
}
+ AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+ if let Some(qself) = qself {
+ try_visit!(visitor.visit_ty(&qself.ty));
+ }
+ try_visit!(visitor.visit_path(prefix, item.id));
+ for (ident, rename) in suffixes {
+ visitor.visit_ident(*ident);
+ if let Some(rename) = rename {
+ visitor.visit_ident(*rename);
+ }
+ }
+ visit_opt!(visitor, visit_block, body);
+ }
}
V::Result::output()
}
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 61fb5c16ad612..1255c1bba0876 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -460,8 +460,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
delegation_results.body_id,
)
}
- ItemKind::MacCall(..) => {
- panic!("`TyMac` should have been expanded by now")
+ ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
+ panic!("macros should have been expanded by now")
}
}
}
@@ -845,7 +845,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
(delegation_results.generics, item_kind, true)
}
- AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
+ AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+ panic!("macros should have been expanded by now")
+ }
};
let item = hir::TraitItem {
@@ -869,7 +871,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
},
- AssocItemKind::MacCall(..) => unimplemented!(),
+ AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+ panic!("macros should have been expanded by now")
+ }
};
let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
hir::TraitItemRef {
@@ -964,7 +968,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
)
}
- AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
+ AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+ panic!("macros should have been expanded by now")
+ }
};
let item = hir::ImplItem {
@@ -993,7 +999,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
},
- AssocItemKind::MacCall(..) => unimplemented!(),
+ AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+ panic!("macros should have been expanded by now")
+ }
},
trait_item_def_id: self
.resolver
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 09f9ca53a7ac0..16c3ee948a480 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -5,6 +5,7 @@ use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
use ast::StaticItem;
use itertools::{Itertools, Position};
use rustc_ast as ast;
+use rustc_ast::ptr::P;
use rustc_ast::ModKind;
use rustc_span::symbol::Ident;
@@ -374,9 +375,22 @@ impl<'a> State<'a> {
state.print_visibility(&item.vis)
});
}
- ast::ItemKind::Delegation(box delegation) => {
- self.print_delegation(delegation, &item.vis, &item.attrs)
- }
+ ast::ItemKind::Delegation(deleg) => self.print_delegation(
+ &item.attrs,
+ &item.vis,
+ &deleg.qself,
+ &deleg.path,
+ None,
+ &deleg.body,
+ ),
+ ast::ItemKind::DelegationMac(deleg) => self.print_delegation(
+ &item.attrs,
+ &item.vis,
+ &deleg.qself,
+ &deleg.prefix,
+ Some(&deleg.suffixes),
+ &deleg.body,
+ ),
}
self.ann.post(self, AnnNode::Item(item))
}
@@ -553,31 +567,63 @@ impl<'a> State<'a> {
self.word(";");
}
}
- ast::AssocItemKind::Delegation(box delegation) => {
- self.print_delegation(delegation, vis, &item.attrs)
- }
+ ast::AssocItemKind::Delegation(deleg) => self.print_delegation(
+ &item.attrs,
+ vis,
+ &deleg.qself,
+ &deleg.path,
+ None,
+ &deleg.body,
+ ),
+ ast::AssocItemKind::DelegationMac(deleg) => self.print_delegation(
+ &item.attrs,
+ vis,
+ &deleg.qself,
+ &deleg.prefix,
+ Some(&deleg.suffixes),
+ &deleg.body,
+ ),
}
self.ann.post(self, AnnNode::SubItem(id))
}
pub(crate) fn print_delegation(
&mut self,
- delegation: &ast::Delegation,
- vis: &ast::Visibility,
attrs: &[ast::Attribute],
+ vis: &ast::Visibility,
+ qself: &Option>,
+ path: &ast::Path,
+ suffixes: Option<&[(Ident, Option)]>,
+ body: &Option>,
) {
- if delegation.body.is_some() {
+ if body.is_some() {
self.head("");
}
self.print_visibility(vis);
- self.word_space("reuse");
+ self.word_nbsp("reuse");
- if let Some(qself) = &delegation.qself {
- self.print_qpath(&delegation.path, qself, false);
+ if let Some(qself) = qself {
+ self.print_qpath(path, qself, false);
} else {
- self.print_path(&delegation.path, false, 0);
+ self.print_path(path, false, 0);
+ }
+ if let Some(suffixes) = suffixes {
+ self.word("::");
+ self.word("{");
+ for (i, (ident, rename)) in suffixes.iter().enumerate() {
+ self.print_ident(*ident);
+ if let Some(rename) = rename {
+ self.nbsp();
+ self.word_nbsp("as");
+ self.print_ident(*rename);
+ }
+ if i != suffixes.len() - 1 {
+ self.word_space(",");
+ }
+ }
+ self.word("}");
}
- if let Some(body) = &delegation.body {
+ if let Some(body) = body {
self.nbsp();
self.print_block_with_attrs(body, attrs);
} else {
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index c51a7744a30a3..26ea95f0f0d50 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -207,13 +207,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
let cond_bitmap = coverage_context
.try_get_mcdc_condition_bitmap(&instance, decision_depth)
.expect("mcdc cond bitmap should have been allocated for merging into the global bitmap");
- let bitmap_bytes = bx.tcx().coverage_ids_info(instance.def).mcdc_bitmap_bytes;
+ let bitmap_bytes = function_coverage_info.mcdc_bitmap_bytes;
assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range");
- assert!(
- bitmap_bytes <= function_coverage_info.mcdc_bitmap_bytes,
- "bitmap length disagreement: query says {bitmap_bytes} but function info only has {}",
- function_coverage_info.mcdc_bitmap_bytes
- );
let fn_name = bx.get_pgo_func_name_var(instance);
let hash = bx.const_u64(function_coverage_info.function_source_hash);
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 1610135a0efad..18bb71bd99f73 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -896,7 +896,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
style: SuggestionStyle,
) -> &mut Self {
suggestion.sort_unstable();
- suggestion.dedup();
+ suggestion.dedup_by(|(s1, m1), (s2, m2)| s1.source_equal(*s2) && m1 == m2);
let parts = suggestion
.into_iter()
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 2cc0167dbaa6e..d9add1c9b3b52 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -106,6 +106,12 @@ impl IntoDiagArg for rustc_type_ir::ExistentialTrait
}
}
+impl IntoDiagArg for rustc_type_ir::UnevaluatedConst {
+ fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+ format!("{self:?}").into_diag_arg()
+ }
+}
+
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
impl IntoDiagArg for bool {
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index b7aae2af9ef97..7ae988a5be6c8 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -30,6 +30,9 @@ expand_duplicate_matcher_binding = duplicate matcher binding
.label = duplicate binding
.label2 = previous binding
+expand_empty_delegation_list =
+ empty list delegation is not supported
+
expand_expected_paren_or_brace =
expected `(` or `{"{"}`, found `{$token}`
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index b0563bfdea749..a5fc9e9d89c1e 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -433,3 +433,10 @@ pub struct ExpectedParenOrBrace<'a> {
pub span: Span,
pub token: Cow<'a, str>,
}
+
+#[derive(Diagnostic)]
+#[diag(expand_empty_delegation_list)]
+pub(crate) struct EmptyDelegationList {
+ #[primary_span]
+ pub span: Span,
+}
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index ddf7b1a007a8e..a049ac251e1e7 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1,8 +1,8 @@
use crate::base::*;
use crate::config::StripUnconfigured;
use crate::errors::{
- IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported,
- UnsupportedKeyValue, WrongFragmentKind,
+ EmptyDelegationList, IncompleteParse, RecursionLimitReached, RemoveExprNotSupported,
+ RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind,
};
use crate::mbe::diagnostics::annotate_err_with_kind;
use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
@@ -1041,6 +1041,7 @@ enum AddSemicolon {
trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
type OutputTy = SmallVec<[Self; 1]>;
type AttrsTy: Deref = ast::AttrVec;
+ type ItemKind = ItemKind;
const KIND: AstFragmentKind;
fn to_annotatable(self) -> Annotatable;
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;
@@ -1059,6 +1060,18 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) {
unreachable!()
}
+ fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> {
+ None
+ }
+ fn delegation_item_kind(_deleg: Box) -> Self::ItemKind {
+ unreachable!()
+ }
+ fn from_item(_item: ast::Item) -> Self {
+ unreachable!()
+ }
+ fn flatten_outputs(_outputs: impl Iterator- ) -> Self::OutputTy {
+ unreachable!()
+ }
fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {}
fn post_flat_map_node_collect_bang(_output: &mut Self::OutputTy, _add_semicolon: AddSemicolon) {
}
@@ -1106,6 +1119,21 @@ impl InvocationCollectorNode for P {
_ => unreachable!(),
}
}
+ fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> {
+ match &self.kind {
+ ItemKind::DelegationMac(deleg) => Some((deleg, self)),
+ _ => None,
+ }
+ }
+ fn delegation_item_kind(deleg: Box) -> Self::ItemKind {
+ ItemKind::Delegation(deleg)
+ }
+ fn from_item(item: ast::Item) -> Self {
+ P(item)
+ }
+ fn flatten_outputs(items: impl Iterator
- ) -> Self::OutputTy {
+ items.flatten().collect()
+ }
fn wrap_flat_map_node_noop_flat_map(
mut node: Self,
collector: &mut InvocationCollector<'_, '_>,
@@ -1214,6 +1242,7 @@ impl InvocationCollectorNode for P {
struct TraitItemTag;
impl InvocationCollectorNode for AstNodeWrapper
, TraitItemTag> {
type OutputTy = SmallVec<[P; 1]>;
+ type ItemKind = AssocItemKind;
const KIND: AstFragmentKind = AstFragmentKind::TraitItems;
fn to_annotatable(self) -> Annotatable {
Annotatable::TraitItem(self.wrapped)
@@ -1234,11 +1263,27 @@ impl InvocationCollectorNode for AstNodeWrapper, TraitItemTag>
_ => unreachable!(),
}
}
+ fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> {
+ match &self.wrapped.kind {
+ AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
+ _ => None,
+ }
+ }
+ fn delegation_item_kind(deleg: Box) -> Self::ItemKind {
+ AssocItemKind::Delegation(deleg)
+ }
+ fn from_item(item: ast::Item) -> Self {
+ AstNodeWrapper::new(P(item), TraitItemTag)
+ }
+ fn flatten_outputs(items: impl Iterator- ) -> Self::OutputTy {
+ items.flatten().collect()
+ }
}
struct ImplItemTag;
impl InvocationCollectorNode for AstNodeWrapper
, ImplItemTag> {
type OutputTy = SmallVec<[P; 1]>;
+ type ItemKind = AssocItemKind;
const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
fn to_annotatable(self) -> Annotatable {
Annotatable::ImplItem(self.wrapped)
@@ -1259,6 +1304,21 @@ impl InvocationCollectorNode for AstNodeWrapper, ImplItemTag>
_ => unreachable!(),
}
}
+ fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> {
+ match &self.wrapped.kind {
+ AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
+ _ => None,
+ }
+ }
+ fn delegation_item_kind(deleg: Box) -> Self::ItemKind {
+ AssocItemKind::Delegation(deleg)
+ }
+ fn from_item(item: ast::Item) -> Self {
+ AstNodeWrapper::new(P(item), ImplItemTag)
+ }
+ fn flatten_outputs(items: impl Iterator- ) -> Self::OutputTy {
+ items.flatten().collect()
+ }
}
impl InvocationCollectorNode for P {
@@ -1420,6 +1480,24 @@ impl InvocationCollectorNode for ast::Stmt {
};
(mac, attrs, if add_semicolon { AddSemicolon::Yes } else { AddSemicolon::No })
}
+ fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> {
+ match &self.kind {
+ StmtKind::Item(item) => match &item.kind {
+ ItemKind::DelegationMac(deleg) => Some((deleg, item)),
+ _ => None,
+ },
+ _ => None,
+ }
+ }
+ fn delegation_item_kind(deleg: Box) -> Self::ItemKind {
+ ItemKind::Delegation(deleg)
+ }
+ fn from_item(item: ast::Item) -> Self {
+ ast::Stmt { id: ast::DUMMY_NODE_ID, span: item.span, kind: StmtKind::Item(P(item)) }
+ }
+ fn flatten_outputs(items: impl Iterator
- ) -> Self::OutputTy {
+ items.flatten().collect()
+ }
fn post_flat_map_node_collect_bang(stmts: &mut Self::OutputTy, add_semicolon: AddSemicolon) {
// If this is a macro invocation with a semicolon, then apply that
// semicolon to the final statement produced by expansion.
@@ -1818,6 +1896,40 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
Node::post_flat_map_node_collect_bang(&mut res, add_semicolon);
res
}
+ None if let Some((deleg, item)) = node.delegation_list() => {
+ if deleg.suffixes.is_empty() {
+ // Report an error for now, to avoid keeping stem for resolution and
+ // stability checks.
+ self.cx.dcx().emit_err(EmptyDelegationList { span: item.span });
+ }
+
+ Node::flatten_outputs(deleg.suffixes.iter().map(|&(ident, rename)| {
+ let mut path = deleg.prefix.clone();
+ path.segments.push(ast::PathSegment {
+ ident,
+ id: ast::DUMMY_NODE_ID,
+ args: None,
+ });
+
+ let mut item = Node::from_item(ast::Item {
+ attrs: item.attrs.clone(),
+ id: ast::DUMMY_NODE_ID,
+ span: ident.span,
+ vis: item.vis.clone(),
+ ident: rename.unwrap_or(ident),
+ kind: Node::delegation_item_kind(Box::new(ast::Delegation {
+ id: ast::DUMMY_NODE_ID,
+ qself: deleg.qself.clone(),
+ path,
+ rename,
+ body: deleg.body.clone(),
+ })),
+ tokens: None,
+ });
+
+ assign_id!(self, item.node_id_mut(), || item.noop_flat_map(self))
+ }))
+ }
None => {
match Node::wrap_flat_map_node_noop_flat_map(node, self, |mut node, this| {
assign_id!(this, node.node_id_mut(), || node.noop_flat_map(this))
@@ -1866,6 +1978,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
self.collect_bang(mac, Node::KIND).make_ast::()
})
}
+ None if node.delegation_list().is_some() => unreachable!(),
None => {
assign_id!(self, node.node_id_mut(), || node.noop_visit(self))
}
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 8239cfd46cbfe..128e9f48ff573 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -23,7 +23,7 @@ pub(crate) enum MetaVarExpr {
/// The length of the repetition at a particular depth, where 0 is the inner-most
/// repetition. The `usize` is the depth.
- Length(usize),
+ Len(usize),
}
impl MetaVarExpr {
@@ -48,13 +48,13 @@ impl MetaVarExpr {
MetaVarExpr::Ignore(parse_ident(&mut iter, psess, ident.span)?)
}
"index" => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?),
- "length" => MetaVarExpr::Length(parse_depth(&mut iter, psess, ident.span)?),
+ "len" => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?),
_ => {
let err_msg = "unrecognized meta-variable expression";
let mut err = psess.dcx.struct_span_err(ident.span, err_msg);
err.span_suggestion(
ident.span,
- "supported expressions are count, ignore, index and length",
+ "supported expressions are count, ignore, index and len",
"",
Applicability::MachineApplicable,
);
@@ -68,7 +68,7 @@ impl MetaVarExpr {
pub(crate) fn ident(&self) -> Option {
match *self {
MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(ident),
- MetaVarExpr::Index(..) | MetaVarExpr::Length(..) => None,
+ MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None,
}
}
}
@@ -111,7 +111,7 @@ fn parse_count<'psess>(
Ok(MetaVarExpr::Count(ident, depth))
}
-/// Parses the depth used by index(depth) and length(depth).
+/// Parses the depth used by index(depth) and len(depth).
fn parse_depth<'psess>(
iter: &mut RefTokenTreeCursor<'_>,
psess: &'psess ParseSess,
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 06c1612ddbaea..2e5596f51c35d 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -357,7 +357,7 @@ fn parse_sep_and_kleene_op<'a>(
// `$$` or a meta-variable is the lhs of a macro but shouldn't.
//
-// For example, `macro_rules! foo { ( ${length()} ) => {} }`
+// For example, `macro_rules! foo { ( ${len()} ) => {} }`
fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &Session, token: &Token) {
sess.dcx()
.span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token)));
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index e35eba0f859b8..3901b82eb52ec 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -685,14 +685,14 @@ fn transcribe_metavar_expr<'a>(
}
None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "index")),
},
- MetaVarExpr::Length(depth) => match repeats.iter().nth_back(depth) {
+ MetaVarExpr::Len(depth) => match repeats.iter().nth_back(depth) {
Some((_, length)) => {
result.push(TokenTree::token_alone(
TokenKind::lit(token::Integer, sym::integer(*length), None),
visited_span(),
));
}
- None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "length")),
+ None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "len")),
},
}
Ok(())
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 706f6f875bf64..6da5adc7a6e9b 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -938,14 +938,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
- pub fn get_conversion_methods(
+ pub fn get_conversion_methods_for_diagnostic(
&self,
span: Span,
expected: Ty<'tcx>,
checked_ty: Ty<'tcx>,
hir_id: hir::HirId,
) -> Vec {
- let methods = self.probe_for_return_type(
+ let methods = self.probe_for_return_type_for_diagnostic(
span,
probe::Mode::MethodCall,
expected,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index f283c0138052e..5a9eab1ffeaf1 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2414,7 +2414,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let guar = if field.name == kw::Empty {
self.dcx().span_delayed_bug(field.span, "field name with no name")
- } else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) {
+ } else if self.method_exists_for_diagnostic(
+ field,
+ base_ty,
+ expr.hir_id,
+ expected.only_has_type(self),
+ ) {
self.ban_take_value_of_method(expr, base_ty, field)
} else if !base_ty.is_primitive_ty() {
self.ban_nonexisting_field(field, base, expr, base_ty)
@@ -2600,7 +2605,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut err = self.private_field_err(field, base_did);
// Also check if an accessible method exists, which is often what is meant.
- if self.method_exists(field, expr_t, expr.hir_id, return_ty)
+ if self.method_exists_for_diagnostic(field, expr_t, expr.hir_id, return_ty)
&& !self.expr_in_place(expr.hir_id)
{
self.suggest_method_call(
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 1864c7e6ef82d..89f62577506fd 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -18,12 +18,12 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorOf, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{HirId, PatKind};
-use rustc_middle::{bug, span_bug};
use rustc_middle::hir::place::ProjectionKind;
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{
self, adjustment, AdtKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _,
};
+use rustc_middle::{bug, span_bug};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use rustc_trait_selection::infer::InferCtxtExt;
@@ -1181,6 +1181,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty);
return Ok(*first_ty);
}
+ } else if let PatKind::Ref(subpat, _) = pat.kind
+ && self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id)
+ {
+ return self.pat_ty_adjusted(subpat);
}
self.pat_ty_unadjusted(pat)
@@ -1712,6 +1716,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
self.cat_pattern(place_with_id, subpat, op)?;
}
+ PatKind::Ref(subpat, _)
+ if self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id) =>
+ {
+ self.cat_pattern(place_with_id, subpat, op)?;
+ }
+
PatKind::Box(subpat) | PatKind::Ref(subpat, _) => {
// box p1, &p1, &mut p1. we can ignore the mutability of
// PatKind::Ref since that information is already contained
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 11f288391c3bd..fe0dd4e393fc8 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -290,7 +290,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
) -> bool {
let expr = expr.peel_blocks();
- let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);
+ let methods =
+ self.get_conversion_methods_for_diagnostic(expr.span, expected, found, expr.hir_id);
if let Some((suggestion, msg, applicability, verbose, annotation)) =
self.suggest_deref_or_ref(expr, found, expected)
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index f82182fa0583c..a40fa600c19e2 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -91,7 +91,7 @@ pub enum CandidateSource {
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Determines whether the type `self_ty` supports a visible method named `method_name` or not.
#[instrument(level = "debug", skip(self))]
- pub fn method_exists(
+ pub fn method_exists_for_diagnostic(
&self,
method_name: Ident,
self_ty: Ty<'tcx>,
@@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
probe::Mode::MethodCall,
method_name,
return_type,
- IsSuggestion(false),
+ IsSuggestion(true),
self_ty,
call_expr_id,
ProbeScope::TraitsInScope,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 81e179c90900c..6cfdacf6a24d2 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -90,6 +90,11 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
>,
scope_expr_id: HirId,
+
+ /// Is this probe being done for a diagnostic? This will skip some error reporting
+ /// machinery, since we don't particularly care about, for example, similarly named
+ /// candidates if we're *reporting* similarly named candidates.
+ is_suggestion: IsSuggestion,
}
impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
@@ -220,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// would use to decide if a method is a plausible fit for
/// ambiguity purposes).
#[instrument(level = "debug", skip(self, candidate_filter))]
- pub fn probe_for_return_type(
+ pub fn probe_for_return_type_for_diagnostic(
&self,
span: Span,
mode: Mode,
@@ -459,6 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&orig_values,
steps.steps,
scope_expr_id,
+ is_suggestion,
);
probe_cx.assemble_inherent_candidates();
@@ -553,6 +559,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
steps: &'tcx [CandidateStep<'tcx>],
scope_expr_id: HirId,
+ is_suggestion: IsSuggestion,
) -> ProbeContext<'a, 'tcx> {
ProbeContext {
fcx,
@@ -570,6 +577,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
static_candidates: RefCell::new(Vec::new()),
unsatisfied_predicates: RefCell::new(Vec::new()),
scope_expr_id,
+ is_suggestion,
}
}
@@ -944,6 +952,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
return r;
}
+ // If it's a `lookup_probe_for_diagnostic`, then quit early. No need to
+ // probe for other candidates.
+ if self.is_suggestion.0 {
+ return Err(MethodError::NoMatch(NoMatchData {
+ static_candidates: vec![],
+ unsatisfied_predicates: vec![],
+ out_of_scope_traits: vec![],
+ similar_candidate: None,
+ mode: self.mode,
+ }));
+ }
+
debug!("pick: actual search failed, assemble diagnostics");
let static_candidates = std::mem::take(self.static_candidates.get_mut());
@@ -1631,6 +1651,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.orig_steps_var_values,
self.steps,
self.scope_expr_id,
+ IsSuggestion(true),
);
pcx.allow_similar_names = true;
pcx.assemble_inherent_candidates();
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index d50e99433842a..db510d44392cb 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1143,7 +1143,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- let label_span_not_found = |err: &mut Diag<'_>| {
+ let mut find_candidate_for_method = false;
+
+ let mut label_span_not_found = |err: &mut Diag<'_>| {
if unsatisfied_predicates.is_empty() {
err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
let is_string_or_ref_str = match rcvr_ty.kind() {
@@ -1219,6 +1221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.note(format!(
"the {item_kind} was found for\n{type_candidates}{additional_types}"
));
+ find_candidate_for_method = mode == Mode::MethodCall;
}
}
} else {
@@ -1371,9 +1374,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
}
- // If an appropriate error source is not found, check method chain for possible candiates
- if unsatisfied_predicates.is_empty()
- && let Mode::MethodCall = mode
+
+ if !find_candidate_for_method {
+ self.lookup_segments_chain_for_no_match_method(
+ &mut err,
+ item_name,
+ item_kind,
+ source,
+ no_match_data,
+ );
+ }
+
+ self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
+ Some(err)
+ }
+
+ /// If an appropriate error source is not found, check method chain for possible candidates
+ fn lookup_segments_chain_for_no_match_method(
+ &self,
+ err: &mut Diag<'_>,
+ item_name: Ident,
+ item_kind: &str,
+ source: SelfSource<'tcx>,
+ no_match_data: &NoMatchData<'tcx>,
+ ) {
+ if no_match_data.unsatisfied_predicates.is_empty()
+ && let Mode::MethodCall = no_match_data.mode
&& let SelfSource::MethodCall(mut source_expr) = source
{
let mut stack_methods = vec![];
@@ -1394,6 +1420,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.unwrap_or(Ty::new_misc_error(self.tcx)),
);
+ // FIXME: `probe_for_name_many` searches for methods in inherent implementations,
+ // so it may return a candidate that doesn't belong to this `revr_ty`. We need to
+ // check whether the instantiated type matches the received one.
for _matched_method in self.probe_for_name_many(
Mode::MethodCall,
item_name,
@@ -1416,8 +1445,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
}
- self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
- Some(err)
}
fn find_likely_intended_associated_item(
@@ -2814,7 +2841,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(output_ty) => self.resolve_vars_if_possible(output_ty),
_ => return,
};
- let method_exists = self.method_exists(item_name, output_ty, call.hir_id, return_type);
+ let method_exists =
+ self.method_exists_for_diagnostic(item_name, output_ty, call.hir_id, return_type);
debug!("suggest_await_before_method: is_method_exist={}", method_exists);
if method_exists {
err.span_suggestion_verbose(
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 8458b53933537..5ad3ff71a6d4a 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -347,5 +347,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
"reduce the glob import's visibility or increase visibility of imported items",
);
}
+ BuiltinLintDiag::MaybeTypo { span, name } => {
+ diag.span_suggestion_verbose(
+ span,
+ "an attribute with a similar name exists",
+ name,
+ Applicability::MachineApplicable,
+ );
+ }
}
}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index ed165188787a5..e06e3e9b805f7 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -663,6 +663,10 @@ pub enum BuiltinLintDiag {
span: Span,
max_vis: String,
},
+ MaybeTypo {
+ span: Span,
+ name: Symbol,
+ },
}
/// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index 477303e2434f4..7f9a5a366d74e 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -129,17 +129,11 @@ pub enum CoverageKind {
/// Marks the point in MIR control flow represented by a evaluated condition.
///
/// This is eventually lowered to `llvm.instrprof.mcdc.condbitmap.update` in LLVM IR.
- ///
- /// If this statement does not survive MIR optimizations, the condition would never be
- /// taken as evaluated.
CondBitmapUpdate { id: ConditionId, value: bool, decision_depth: u16 },
/// Marks the point in MIR control flow represented by a evaluated decision.
///
/// This is eventually lowered to `llvm.instrprof.mcdc.tvbitmap.update` in LLVM IR.
- ///
- /// If this statement does not survive MIR optimizations, the decision would never be
- /// taken as evaluated.
TestVectorBitmapUpdate { bitmap_idx: u32, decision_depth: u16 },
}
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 9a7af6135e46f..9d70231be3b0c 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -362,8 +362,4 @@ pub struct CoverageIdsInfo {
/// InstrumentCoverage MIR pass, if the highest-numbered counter increments
/// were removed by MIR optimizations.
pub max_counter_id: mir::coverage::CounterId,
-
- /// Coverage codegen for mcdc needs to know the size of the global bitmap so that it can
- /// set the `bytemap-bytes` argument of the `llvm.instrprof.mcdc.tvbitmap.update` intrinsic.
- pub mcdc_bitmap_bytes: u32,
}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 4278ce823d0e0..e124b478f4193 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1480,13 +1480,17 @@ pub enum BinOp {
BitOr,
/// The `<<` operator (shift left)
///
- /// The offset is truncated to the size of the first operand and made unsigned before shifting.
+ /// The offset is (uniquely) determined as follows:
+ /// - it is "equal modulo LHS::BITS" to the RHS
+ /// - it is in the range `0..LHS::BITS`
Shl,
/// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0
ShlUnchecked,
/// The `>>` operator (shift right)
///
- /// The offset is truncated to the size of the first operand and made unsigned before shifting.
+ /// The offset is (uniquely) determined as follows:
+ /// - it is "equal modulo LHS::BITS" to the RHS
+ /// - it is in the range `0..LHS::BITS`
///
/// This is an arithmetic shift if the LHS is signed
/// and a logical shift if the LHS is unsigned.
diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs
index 2ddcb8aab2530..9e94489902674 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect.rs
@@ -153,6 +153,8 @@ pub enum ProbeKind<'tcx> {
/// do a probe to find out what projection type(s) may be used to prove that
/// the source type upholds all of the target type's object bounds.
UpcastProjectionCompatibility,
+ /// Looking for param-env candidates that satisfy the trait ref for a projection.
+ ShadowedEnvProbing,
/// Try to unify an opaque type with an existing key in the storage.
OpaqueTypeStorageLookup { result: QueryResult<'tcx> },
}
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index e652f0586c4ea..5b3c50cb97323 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -118,6 +118,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
ProbeKind::TraitCandidate { source, result } => {
write!(self.f, "CANDIDATE {source:?}: {result:?}")
}
+ ProbeKind::ShadowedEnvProbing => {
+ write!(self.f, "PROBING FOR IMPLS SHADOWED BY PARAM-ENV CANDIDATE:")
+ }
}?;
self.nested(|this| {
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 329d5f34a2123..9dc30447f0e57 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -7,8 +7,7 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
-use rustc_type_ir::ConstKind as IrConstKind;
-use rustc_type_ir::{TypeFlags, WithCachedTypeInfo};
+use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
mod int;
mod kind;
@@ -20,7 +19,8 @@ use rustc_span::Span;
use rustc_span::DUMMY_SP;
pub use valtree::*;
-pub type ConstKind<'tcx> = IrConstKind>;
+pub type ConstKind<'tcx> = ir::ConstKind>;
+pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst>;
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
@@ -184,6 +184,14 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> {
Const::new_bound(tcx, debruijn, var, ty)
}
+ fn new_unevaluated(
+ interner: TyCtxt<'tcx>,
+ uv: ty::UnevaluatedConst<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> Self {
+ Const::new_unevaluated(interner, uv, ty)
+ }
+
fn ty(self) -> Ty<'tcx> {
self.ty()
}
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 7e49b0ac915c6..d7ae050ed4d02 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,30 +1,15 @@
use super::Const;
use crate::mir;
use crate::ty::abstract_const::CastKind;
-use crate::ty::GenericArgsRef;
use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt};
-use rustc_hir::def_id::DefId;
-use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
-/// An unevaluated (potentially generic) constant used in the type-system.
-#[derive(Copy, Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
-#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
-pub struct UnevaluatedConst<'tcx> {
- pub def: DefId,
- pub args: GenericArgsRef<'tcx>,
-}
-
-impl rustc_errors::IntoDiagArg for UnevaluatedConst<'_> {
- fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
- format!("{self:?}").into_diag_arg()
- }
-}
-
-impl<'tcx> UnevaluatedConst<'tcx> {
+#[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
+impl<'tcx> ty::UnevaluatedConst<'tcx> {
/// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this
/// hurts performance.
#[inline]
- pub(crate) fn prepare_for_eval(
+ fn prepare_for_eval(
self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@@ -55,13 +40,6 @@ impl<'tcx> UnevaluatedConst<'tcx> {
}
}
-impl<'tcx> UnevaluatedConst<'tcx> {
- #[inline]
- pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> {
- UnevaluatedConst { def, args }
- }
-}
-
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
pub enum Expr<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index e831db1a41bf8..d7e185dd5e107 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -76,6 +76,7 @@ use rustc_type_ir::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
+use std::assert_matches::assert_matches;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt;
@@ -91,67 +92,124 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type DefiningOpaqueTypes = &'tcx ty::List;
type AdtDef = ty::AdtDef<'tcx>;
type GenericArgs = ty::GenericArgsRef<'tcx>;
+ type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>];
type GenericArg = ty::GenericArg<'tcx>;
- type Term = ty::Term<'tcx>;
+ type Term = ty::Term<'tcx>;
type Binder>> = Binder<'tcx, T>;
type BoundVars = &'tcx List;
type BoundVar = ty::BoundVariableKind;
- type CanonicalVars = CanonicalVarInfos<'tcx>;
+ type CanonicalVars = CanonicalVarInfos<'tcx>;
type Ty = Ty<'tcx>;
type Tys = &'tcx List>;
- type AliasTy = ty::AliasTy<'tcx>;
type ParamTy = ParamTy;
type BoundTy = ty::BoundTy;
type PlaceholderTy = ty::PlaceholderType;
- type ErrorGuaranteed = ErrorGuaranteed;
+ type ErrorGuaranteed = ErrorGuaranteed;
type BoundExistentialPredicates = &'tcx List>;
type PolyFnSig = PolyFnSig<'tcx>;
type AllocId = crate::mir::interpret::AllocId;
- type Pat = Pattern<'tcx>;
+ type Pat = Pattern<'tcx>;
type Const = ty::Const<'tcx>;
type AliasConst = ty::UnevaluatedConst<'tcx>;
type PlaceholderConst = ty::PlaceholderConst;
type ParamConst = ty::ParamConst;
type BoundConst = ty::BoundVar;
type ValueConst = ty::ValTree<'tcx>;
- type ExprConst = ty::Expr<'tcx>;
+ type ExprConst = ty::Expr<'tcx>;
type Region = Region<'tcx>;
type EarlyParamRegion = ty::EarlyParamRegion;
type LateParamRegion = ty::LateParamRegion;
type BoundRegion = ty::BoundRegion;
type InferRegion = ty::RegionVid;
- type PlaceholderRegion = ty::PlaceholderRegion;
+ type PlaceholderRegion = ty::PlaceholderRegion;
type Predicate = Predicate<'tcx>;
type TraitPredicate = ty::TraitPredicate<'tcx>;
type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>;
type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>;
type ProjectionPredicate = ty::ProjectionPredicate<'tcx>;
- type AliasTerm = ty::AliasTerm<'tcx>;
type NormalizesTo = ty::NormalizesTo<'tcx>;
type SubtypePredicate = ty::SubtypePredicate<'tcx>;
type CoercePredicate = ty::CoercePredicate<'tcx>;
type ClosureKind = ty::ClosureKind;
- type Clauses = ty::Clauses<'tcx>;
+ type Clauses = ty::Clauses<'tcx>;
fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> Self::CanonicalVars {
self.mk_canonical_var_infos(infos)
}
type GenericsOf = &'tcx ty::Generics;
+
fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics {
self.generics_of(def_id)
}
+ fn type_of_instantiated(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Ty<'tcx> {
+ self.type_of(def_id).instantiate(self, args)
+ }
+
+ fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind {
+ match self.def_kind(alias.def_id) {
+ DefKind::AssocTy => {
+ if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id))
+ {
+ ty::Inherent
+ } else {
+ ty::Projection
+ }
+ }
+ DefKind::OpaqueTy => ty::Opaque,
+ DefKind::TyAlias => ty::Weak,
+ kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
+ }
+ }
+
+ fn alias_term_kind(self, alias: ty::AliasTerm<'tcx>) -> ty::AliasTermKind {
+ match self.def_kind(alias.def_id) {
+ DefKind::AssocTy => {
+ if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id))
+ {
+ ty::AliasTermKind::InherentTy
+ } else {
+ ty::AliasTermKind::ProjectionTy
+ }
+ }
+ DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
+ DefKind::TyAlias => ty::AliasTermKind::WeakTy,
+ DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
+ DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
+ kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
+ }
+ }
+
+ fn trait_ref_and_own_args_for_alias(
+ self,
+ def_id: Self::DefId,
+ args: Self::GenericArgs,
+ ) -> (rustc_type_ir::TraitRef, Self::GenericArgsSlice) {
+ assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst);
+ let trait_def_id = self.parent(def_id);
+ assert_matches!(self.def_kind(trait_def_id), DefKind::Trait);
+ let trait_generics = self.generics_of(trait_def_id);
+ (
+ ty::TraitRef::new(self, trait_def_id, args.truncate_to(self, trait_generics)),
+ &args[trait_generics.count()..],
+ )
+ }
+
fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs {
self.mk_args(args)
}
+ fn mk_args_from_iter(self, args: impl Iterator
- ) -> Self::GenericArgs {
+ self.mk_args_from_iter(args)
+ }
+
fn check_and_mk_args(
self,
def_id: DefId,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index dc5e881843a54..93ccc0a7de420 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -96,9 +96,9 @@ pub use self::list::{List, ListWithCachedTypeInfo};
pub use self::parameterized::ParameterizedOverTcx;
pub use self::pattern::{Pattern, PatternKind};
pub use self::predicate::{
- Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialPredicateStableCmpExt,
- ExistentialProjection, ExistentialTraitRef, NormalizesTo, OutlivesPredicate,
- PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
+ AliasTerm, Clause, ClauseKind, CoercePredicate, ExistentialPredicate,
+ ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef, NormalizesTo,
+ OutlivesPredicate, PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate,
PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef,
@@ -110,11 +110,11 @@ pub use self::region::{
};
pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::{
- AliasTerm, AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind,
- CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts,
- CoroutineClosureArgs, CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig,
- InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut,
- UpvarArgs, VarianceDiagInfo,
+ AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
+ ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs,
+ CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs,
+ InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs,
+ VarianceDiagInfo,
};
pub use self::trait_def::TraitDef;
pub use self::typeck_results::{
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index e78856517b217..16ca098853eea 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -13,6 +13,7 @@ use crate::ty::{
};
pub type TraitRef<'tcx> = ir::TraitRef>;
+pub type AliasTerm<'tcx> = ir::AliasTerm>;
pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate>;
pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate>;
pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef>;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 8d8ed70a7574d..3577db7234d90 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3038,6 +3038,33 @@ define_print! {
p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
}
+ ty::AliasTy<'tcx> {
+ let alias_term: ty::AliasTerm<'tcx> = (*self).into();
+ p!(print(alias_term))
+ }
+
+ ty::AliasTerm<'tcx> {
+ match self.kind(cx.tcx()) {
+ ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
+ ty::AliasTermKind::ProjectionTy
+ | ty::AliasTermKind::WeakTy
+ | ty::AliasTermKind::OpaqueTy
+ | ty::AliasTermKind::UnevaluatedConst
+ | ty::AliasTermKind::ProjectionConst => {
+ // If we're printing verbosely, or don't want to invoke queries
+ // (`is_impl_trait_in_trait`), then fall back to printing the def path.
+ // This is likely what you want if you're debugging the compiler anyways.
+ if !(cx.should_print_verbose() || with_reduced_queries())
+ && cx.tcx().is_impl_trait_in_trait(self.def_id)
+ {
+ return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
+ } else {
+ p!(print_def_path(self.def_id, self.args));
+ }
+ }
+ }
+ }
+
ty::TraitPredicate<'tcx> {
p!(print(self.trait_ref.self_ty()), ": ");
p!(pretty_print_bound_constness(self.trait_ref));
@@ -3205,33 +3232,6 @@ define_print_and_forward_display! {
}
}
- ty::AliasTy<'tcx> {
- let alias_term: ty::AliasTerm<'tcx> = (*self).into();
- p!(print(alias_term))
- }
-
- ty::AliasTerm<'tcx> {
- match self.kind(cx.tcx()) {
- ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
- ty::AliasTermKind::ProjectionTy
- | ty::AliasTermKind::WeakTy
- | ty::AliasTermKind::OpaqueTy
- | ty::AliasTermKind::UnevaluatedConst
- | ty::AliasTermKind::ProjectionConst => {
- // If we're printing verbosely, or don't want to invoke queries
- // (`is_impl_trait_in_trait`), then fall back to printing the def path.
- // This is likely what you want if you're debugging the compiler anyways.
- if !(cx.should_print_verbose() || with_reduced_queries())
- && cx.tcx().is_impl_trait_in_trait(self.def_id)
- {
- return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
- } else {
- p!(print_def_path(self.def_id, self.args));
- }
- }
- }
- }
-
ty::Predicate<'tcx> {
p!(print(self.kind()))
}
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 6abd685343b3a..7523cd1532070 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -7,7 +7,7 @@ use crate::mir::interpret;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
+use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult;
use rustc_hir::def::Namespace;
@@ -164,23 +164,6 @@ impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
}
}
-impl<'tcx> fmt::Debug for AliasTy<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- WithInfcx::with_no_infcx(self).fmt(f)
- }
-}
-impl<'tcx> DebugWithInfcx> for AliasTy<'tcx> {
- fn fmt>>(
- this: WithInfcx<'_, Infcx, &Self>,
- f: &mut core::fmt::Formatter<'_>,
- ) -> core::fmt::Result {
- f.debug_struct("AliasTy")
- .field("args", &this.map(|data| data.args))
- .field("def_id", &this.data.def_id)
- .finish()
- }
-}
-
impl<'tcx> DebugWithInfcx> for Pattern<'tcx> {
fn fmt>>(
this: WithInfcx<'_, Infcx, &Self>,
@@ -230,23 +213,6 @@ impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> {
}
}
-impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- WithInfcx::with_no_infcx(self).fmt(f)
- }
-}
-impl<'tcx> DebugWithInfcx> for ty::UnevaluatedConst<'tcx> {
- fn fmt>>(
- this: WithInfcx<'_, Infcx, &Self>,
- f: &mut core::fmt::Formatter<'_>,
- ) -> core::fmt::Result {
- f.debug_struct("UnevaluatedConst")
- .field("def", &this.data.def)
- .field("args", &this.wrap(this.data.args))
- .finish()
- }
-}
-
impl<'tcx> fmt::Debug for ty::Const<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 163016332475e..74b03d6db66db 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -28,20 +28,17 @@ use std::iter;
use std::ops::{ControlFlow, Deref, Range};
use ty::util::IntTypeExt;
-use rustc_type_ir::BoundVar;
-use rustc_type_ir::CollectAndApply;
-use rustc_type_ir::DynKind;
-use rustc_type_ir::TyKind as IrTyKind;
use rustc_type_ir::TyKind::*;
-use rustc_type_ir::TypeAndMut as IrTypeAndMut;
+use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind};
use super::fold::FnMutDelegate;
use super::GenericParamDefKind;
// Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
#[rustc_diagnostic_item = "TyKind"]
-pub type TyKind<'tcx> = IrTyKind>;
-pub type TypeAndMut<'tcx> = IrTypeAndMut>;
+pub type TyKind<'tcx> = ir::TyKind>;
+pub type TypeAndMut<'tcx> = ir::TypeAndMut>;
+pub type AliasTy<'tcx> = ir::AliasTy>;
pub trait Article {
fn article(&self) -> &'static str;
@@ -1105,371 +1102,6 @@ where
}
}
-/// Represents the unprojected term of a projection goal.
-///
-/// * For a projection, this would be `>::N<...>`.
-/// * For an inherent projection, this would be `Ty::N<...>`.
-/// * For an opaque type, there is no explicit syntax.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct AliasTerm<'tcx> {
- /// The parameters of the associated or opaque item.
- ///
- /// For a projection, these are the generic parameters for the trait and the
- /// GAT parameters, if there are any.
- ///
- /// For an inherent projection, they consist of the self type and the GAT parameters,
- /// if there are any.
- ///
- /// For RPIT the generic parameters are for the generics of the function,
- /// while for TAIT it is used for the generic parameters of the alias.
- pub args: GenericArgsRef<'tcx>,
-
- /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
- /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
- /// this is an opaque.
- ///
- /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
- /// underlying type if the type is an opaque.
- ///
- /// Note that if this is an associated type, this is not the `DefId` of the
- /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
- /// aka. `tcx.parent(def_id)`.
- pub def_id: DefId,
-
- /// This field exists to prevent the creation of `AliasTerm` without using
- /// [AliasTerm::new].
- _use_alias_term_new_instead: (),
-}
-
-// FIXME: Remove these when we uplift `AliasTerm`
-use crate::ty::{DebugWithInfcx, InferCtxtLike, WithInfcx};
-impl<'tcx> std::fmt::Debug for AliasTerm<'tcx> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- WithInfcx::with_no_infcx(self).fmt(f)
- }
-}
-impl<'tcx> DebugWithInfcx> for AliasTerm<'tcx> {
- fn fmt>>(
- this: WithInfcx<'_, Infcx, &Self>,
- f: &mut std::fmt::Formatter<'_>,
- ) -> std::fmt::Result {
- f.debug_struct("AliasTerm")
- .field("args", &this.map(|data| data.args))
- .field("def_id", &this.data.def_id)
- .finish()
- }
-}
-
-impl<'tcx> rustc_type_ir::inherent::AliasTerm> for AliasTerm<'tcx> {
- fn new(
- interner: TyCtxt<'tcx>,
- trait_def_id: DefId,
- args: impl IntoIterator>>,
- ) -> Self {
- AliasTerm::new(interner, trait_def_id, args)
- }
-
- fn def_id(self) -> DefId {
- self.def_id
- }
-
- fn args(self) -> ty::GenericArgsRef<'tcx> {
- self.args
- }
-
- fn trait_def_id(self, interner: TyCtxt<'tcx>) -> DefId {
- self.trait_def_id(interner)
- }
-
- fn self_ty(self) -> Ty<'tcx> {
- self.self_ty()
- }
-
- fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
- self.with_self_ty(tcx, self_ty)
- }
-}
-
-impl<'tcx> AliasTerm<'tcx> {
- pub fn new(
- tcx: TyCtxt<'tcx>,
- def_id: DefId,
- args: impl IntoIterator>>,
- ) -> AliasTerm<'tcx> {
- let args = tcx.check_and_mk_args(def_id, args);
- AliasTerm { def_id, args, _use_alias_term_new_instead: () }
- }
-
- pub fn expect_ty(self, tcx: TyCtxt<'tcx>) -> AliasTy<'tcx> {
- match self.kind(tcx) {
- ty::AliasTermKind::ProjectionTy
- | ty::AliasTermKind::InherentTy
- | ty::AliasTermKind::OpaqueTy
- | ty::AliasTermKind::WeakTy => {}
- ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
- bug!("Cannot turn `UnevaluatedConst` into `AliasTy`")
- }
- }
- ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
- }
-
- pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTermKind {
- match tcx.def_kind(self.def_id) {
- DefKind::AssocTy => {
- if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) {
- ty::AliasTermKind::InherentTy
- } else {
- ty::AliasTermKind::ProjectionTy
- }
- }
- DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
- DefKind::TyAlias => ty::AliasTermKind::WeakTy,
- DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
- DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
- kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
- }
- }
-}
-
-/// The following methods work only with (trait) associated item projections.
-impl<'tcx> AliasTerm<'tcx> {
- pub fn self_ty(self) -> Ty<'tcx> {
- self.args.type_at(0)
- }
-
- pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
- AliasTerm::new(
- tcx,
- self.def_id,
- [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
- )
- }
-
- pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
- match tcx.def_kind(self.def_id) {
- DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
- kind => bug!("expected a projection AliasTy; found {kind:?}"),
- }
- }
-
- /// Extracts the underlying trait reference from this projection.
- /// For example, if this is a projection of `::Item`,
- /// then this function would return a `T: Iterator` trait reference.
- ///
- /// NOTE: This will drop the args for generic associated types
- /// consider calling [Self::trait_ref_and_own_args] to get those
- /// as well.
- pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
- let def_id = self.trait_def_id(tcx);
- ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id)))
- }
-
- /// Extracts the underlying trait reference and own args from this projection.
- /// For example, if this is a projection of `::Item<'a>`,
- /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args
- pub fn trait_ref_and_own_args(
- self,
- tcx: TyCtxt<'tcx>,
- ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
- let trait_def_id = self.trait_def_id(tcx);
- let trait_generics = tcx.generics_of(trait_def_id);
- (
- ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)),
- &self.args[trait_generics.count()..],
- )
- }
-
- pub fn to_term(self, tcx: TyCtxt<'tcx>) -> ty::Term<'tcx> {
- match self.kind(tcx) {
- ty::AliasTermKind::ProjectionTy => Ty::new_alias(
- tcx,
- ty::Projection,
- AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
- )
- .into(),
- ty::AliasTermKind::InherentTy => Ty::new_alias(
- tcx,
- ty::Inherent,
- AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
- )
- .into(),
- ty::AliasTermKind::OpaqueTy => Ty::new_alias(
- tcx,
- ty::Opaque,
- AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
- )
- .into(),
- ty::AliasTermKind::WeakTy => Ty::new_alias(
- tcx,
- ty::Weak,
- AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
- )
- .into(),
- ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
- ty::Const::new_unevaluated(
- tcx,
- ty::UnevaluatedConst::new(self.def_id, self.args),
- tcx.type_of(self.def_id).instantiate(tcx, self.args),
- )
- .into()
- }
- }
- }
-}
-
-impl<'tcx> From> for AliasTerm<'tcx> {
- fn from(ty: AliasTy<'tcx>) -> Self {
- AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
- }
-}
-
-impl<'tcx> From> for AliasTerm<'tcx> {
- fn from(ct: ty::UnevaluatedConst<'tcx>) -> Self {
- AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
- }
-}
-
-/// Represents the projection of an associated, opaque, or lazy-type-alias type.
-///
-/// * For a projection, this would be `>::N<...>`.
-/// * For an inherent projection, this would be `Ty::N<...>`.
-/// * For an opaque type, there is no explicit syntax.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct AliasTy<'tcx> {
- /// The parameters of the associated or opaque type.
- ///
- /// For a projection, these are the generic parameters for the trait and the
- /// GAT parameters, if there are any.
- ///
- /// For an inherent projection, they consist of the self type and the GAT parameters,
- /// if there are any.
- ///
- /// For RPIT the generic parameters are for the generics of the function,
- /// while for TAIT it is used for the generic parameters of the alias.
- pub args: GenericArgsRef<'tcx>,
-
- /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
- /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
- /// this is an opaque.
- ///
- /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
- /// underlying type if the type is an opaque.
- ///
- /// Note that if this is an associated type, this is not the `DefId` of the
- /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
- /// aka. `tcx.parent(def_id)`.
- pub def_id: DefId,
-
- /// This field exists to prevent the creation of `AliasT` without using
- /// [AliasTy::new].
- _use_alias_ty_new_instead: (),
-}
-
-impl<'tcx> AliasTy<'tcx> {
- pub fn new(
- tcx: TyCtxt<'tcx>,
- def_id: DefId,
- args: impl IntoIterator>>,
- ) -> ty::AliasTy<'tcx> {
- let args = tcx.check_and_mk_args(def_id, args);
- ty::AliasTy { def_id, args, _use_alias_ty_new_instead: () }
- }
-
- pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTyKind {
- match tcx.def_kind(self.def_id) {
- DefKind::AssocTy
- if let DefKind::Impl { of_trait: false } =
- tcx.def_kind(tcx.parent(self.def_id)) =>
- {
- ty::Inherent
- }
- DefKind::AssocTy => ty::Projection,
- DefKind::OpaqueTy => ty::Opaque,
- DefKind::TyAlias => ty::Weak,
- kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
- }
- }
-
- /// Whether this alias type is an opaque.
- pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool {
- matches!(self.kind(tcx), ty::Opaque)
- }
-
- pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- Ty::new_alias(tcx, self.kind(tcx), self)
- }
-}
-
-/// The following methods work only with (trait) associated type projections.
-impl<'tcx> AliasTy<'tcx> {
- pub fn self_ty(self) -> Ty<'tcx> {
- self.args.type_at(0)
- }
-
- pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
- AliasTy::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1)))
- }
-
- pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
- match tcx.def_kind(self.def_id) {
- DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
- kind => bug!("expected a projection AliasTy; found {kind:?}"),
- }
- }
-
- /// Extracts the underlying trait reference and own args from this projection.
- /// For example, if this is a projection of `::Item<'a>`,
- /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args
- pub fn trait_ref_and_own_args(
- self,
- tcx: TyCtxt<'tcx>,
- ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
- let trait_def_id = self.trait_def_id(tcx);
- let trait_generics = tcx.generics_of(trait_def_id);
- (
- ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)),
- &self.args[trait_generics.count()..],
- )
- }
-
- /// Extracts the underlying trait reference from this projection.
- /// For example, if this is a projection of `::Item`,
- /// then this function would return a `T: Iterator` trait reference.
- ///
- /// WARNING: This will drop the args for generic associated types
- /// consider calling [Self::trait_ref_and_own_args] to get those
- /// as well.
- pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
- let def_id = self.trait_def_id(tcx);
- ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id)))
- }
-}
-
-/// The following methods work only with inherent associated type projections.
-impl<'tcx> AliasTy<'tcx> {
- /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that.
- ///
- /// Does the following transformation:
- ///
- /// ```text
- /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
- ///
- /// I_i impl args
- /// P_j GAT args
- /// ```
- pub fn rebase_inherent_args_onto_impl(
- self,
- impl_args: ty::GenericArgsRef<'tcx>,
- tcx: TyCtxt<'tcx>,
- ) -> ty::GenericArgsRef<'tcx> {
- debug_assert_eq!(self.kind(tcx), ty::Inherent);
-
- tcx.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1)))
- }
-}
-
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct GenSig<'tcx> {
pub resume_ty: Ty<'tcx>,
@@ -2020,6 +1652,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> {
fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
}
+
+ fn new_alias(
+ interner: TyCtxt<'tcx>,
+ kind: ty::AliasTyKind,
+ alias_ty: ty::AliasTy<'tcx>,
+ ) -> Self {
+ Ty::new_alias(interner, kind, alias_ty)
+ }
}
/// Type utilities
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 04ce3de887441..7f3d6a713d914 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1130,7 +1130,7 @@ impl<'tcx> TypeFolder> for WeakAliasTypeExpander<'tcx> {
}
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
- if !ct.ty().has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
+ if !ct.has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
return ct;
}
ct.super_fold_with(self)
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index f77ee63d02c20..65715253647a8 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -61,17 +61,7 @@ fn coverage_ids_info<'tcx>(
.max()
.unwrap_or(CounterId::ZERO);
- let mcdc_bitmap_bytes = mir_body
- .coverage_branch_info
- .as_deref()
- .map(|info| {
- info.mcdc_decision_spans
- .iter()
- .fold(0, |acc, decision| acc + (1_u32 << decision.conditions_num).div_ceil(8))
- })
- .unwrap_or_default();
-
- CoverageIdsInfo { max_counter_id, mcdc_bitmap_bytes }
+ CoverageIdsInfo { max_counter_id }
}
fn all_coverage_in_mir_body<'a, 'tcx>(
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 34cdf8a9b5f8a..3e1be6461eb1e 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -686,20 +686,35 @@ impl<'a> Parser<'a> {
(None, self.parse_path(PathStyle::Expr)?)
};
- let rename = if self.eat_keyword(kw::As) { Some(self.parse_ident()?) } else { None };
+ let rename = |this: &mut Self| {
+ Ok(if this.eat_keyword(kw::As) { Some(this.parse_ident()?) } else { None })
+ };
+ let body = |this: &mut Self| {
+ Ok(if this.check(&token::OpenDelim(Delimiter::Brace)) {
+ Some(this.parse_block()?)
+ } else {
+ this.expect(&token::Semi)?;
+ None
+ })
+ };
- let body = if self.check(&token::OpenDelim(Delimiter::Brace)) {
- Some(self.parse_block()?)
+ let (ident, item_kind) = if self.eat(&token::PathSep) {
+ let (suffixes, _) = self.parse_delim_comma_seq(Delimiter::Brace, |p| {
+ Ok((p.parse_path_segment_ident()?, rename(p)?))
+ })?;
+ let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? };
+ (Ident::empty(), ItemKind::DelegationMac(Box::new(deleg)))
} else {
- self.expect(&token::Semi)?;
- None
+ let rename = rename(self)?;
+ let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
+ let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body: body(self)? };
+ (ident, ItemKind::Delegation(Box::new(deleg)))
};
+
let span = span.to(self.prev_token.span);
self.psess.gated_spans.gate(sym::fn_delegation, span);
- let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
- let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body };
- Ok((ident, ItemKind::Delegation(Box::new(deleg))))
+ Ok((ident, item_kind))
}
fn parse_item_list(
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index c37d3f0441d0b..d845e8ab90d51 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -95,12 +95,15 @@ impl<'a> Parser<'a> {
debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
}
- if !self.recover_colon_before_qpath_proj() {
+ let is_import_coupler = self.is_import_coupler();
+ if !is_import_coupler && !self.recover_colon_before_qpath_proj() {
self.expect(&token::PathSep)?;
}
let qself = P(QSelf { ty, path_span, position: path.segments.len() });
- self.parse_path_segments(&mut path.segments, style, None)?;
+ if !is_import_coupler {
+ self.parse_path_segments(&mut path.segments, style, None)?;
+ }
Ok((
qself,
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index d7664d1c1fff7..a980d5dcaba4b 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -522,7 +522,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
Impl,
MacCall,
MacroDef,
- Delegation
+ Delegation,
+ DelegationMac
]
);
ast_visit::walk_item(self, i)
@@ -650,7 +651,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
record_variants!(
(self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind),
- [Const, Fn, Type, MacCall, Delegation]
+ [Const, Fn, Type, MacCall, Delegation, DelegationMac]
);
ast_visit::walk_assoc_item(self, i, ctxt);
}
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index c1da8928f3021..a5fa94faeadcd 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -285,7 +285,9 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias,
ast::ItemKind::Impl(_) => Target::Impl,
ast::ItemKind::MacroDef(_) => Target::MacroDef,
- ast::ItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
+ ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => {
+ unreachable!("macros should have been expanded")
+ }
};
self.check_for_lang(
@@ -340,7 +342,9 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
}
ast::AssocItemKind::Const(ct) => (Target::AssocConst, Some(&ct.generics)),
ast::AssocItemKind::Type(ty) => (Target::AssocTy, Some(&ty.generics)),
- ast::AssocItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
+ ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(_) => {
+ unreachable!("macros should have been expanded")
+ }
};
self.check_for_lang(
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 3467f1c3edfda..3e9aa3e0a6f21 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -825,7 +825,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
}
ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
- ItemKind::MacroDef(..) | ItemKind::MacCall(_) => unreachable!(),
+ ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
+ unreachable!()
+ }
}
}
@@ -1381,7 +1383,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
| AssocItemKind::Delegation(..)
| AssocItemKind::Fn(..) => ValueNS,
AssocItemKind::Type(..) => TypeNS,
- AssocItemKind::MacCall(_) => bug!(), // handled above
+ AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above
};
let parent = self.parent_scope.module;
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index a27a6bceda335..741a650da55e0 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -139,6 +139,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
ItemKind::Use(..) => return visit::walk_item(self, i),
ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
+ ItemKind::DelegationMac(..) => unreachable!(),
};
let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span);
@@ -278,6 +279,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
AssocItemKind::Const(..) => DefKind::AssocConst,
AssocItemKind::Type(..) => DefKind::AssocTy,
AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
+ AssocItemKind::DelegationMac(..) => unreachable!(),
};
let def = self.create_def(i.id, i.ident.name, def_kind, i.span);
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 3443bbe6e1158..074bf810eaf4b 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -236,7 +236,7 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't
ast::ItemKind::Impl(..) => return,
// Should be unreachable at this stage
- ast::ItemKind::MacCall(..) => panic!(
+ ast::ItemKind::MacCall(..) | ast::ItemKind::DelegationMac(..) => panic!(
"ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
),
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 5dd95a1896bb1..322f2922f9253 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2561,7 +2561,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
ItemKind::ExternCrate(..) => {}
- ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
+ ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
+ panic!("unexpanded macro in resolve!")
+ }
}
}
@@ -2849,7 +2851,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
}),
- AssocItemKind::MacCall(_) => {
+ AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
panic!("unexpanded macro in resolve!")
}
};
@@ -3116,7 +3118,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
},
);
}
- AssocItemKind::MacCall(_) => {
+ AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
panic!("unexpanded macro in resolve!")
}
}
@@ -3218,7 +3220,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
AssocItemKind::Fn(..) => (E0324, "method"),
AssocItemKind::Type(..) => (E0325, "type"),
AssocItemKind::Delegation(..) => (E0324, "method"),
- AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
+ AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+ span_bug!(span, "unexpanded macro")
+ }
};
let trait_path = path_names_to_string(path);
self.report_error(
@@ -4790,7 +4794,8 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
| ItemKind::ExternCrate(..)
| ItemKind::MacroDef(..)
| ItemKind::GlobalAsm(..)
- | ItemKind::MacCall(..) => {}
+ | ItemKind::MacCall(..)
+ | ItemKind::DelegationMac(..) => {}
ItemKind::Delegation(..) => {
// Delegated functions have lifetimes, their count is not necessarily zero.
// But skipping the delegation items here doesn't mean that the count will be considered zero,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 64451030adf0f..12815291c1d1c 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2045,7 +2045,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
AssocSuggestion::MethodWithSelf { called }
}
ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called },
- ast::AssocItemKind::MacCall(_) => continue,
+ ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(..) => {
+ continue;
+ }
});
}
}
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 35bf3f761df39..e3cfe6a6e05a5 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -29,6 +29,7 @@ use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE};
use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES};
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::parse::feature_err;
+use rustc_span::edit_distance::edit_distance;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::hygiene::{AstPass, MacroKind};
@@ -568,15 +569,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
- && path.segments.len() >= 2
- && path.segments[0].ident.name == sym::diagnostic
- && path.segments[1].ident.name != sym::on_unimplemented
+ && let [namespace, attribute, ..] = &*path.segments
+ && namespace.ident.name == sym::diagnostic
+ && attribute.ident.name != sym::on_unimplemented
{
- self.tcx.sess.psess.buffer_lint(
+ let distance =
+ edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
+
+ let help = if distance.is_some() {
+ BuiltinLintDiag::MaybeTypo { span: attribute.span(), name: sym::on_unimplemented }
+ } else {
+ BuiltinLintDiag::Normal
+ };
+ self.tcx.sess.psess.buffer_lint_with_diagnostic(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
- path.segments[1].span(),
+ attribute.span(),
node_id,
"unknown diagnostic attribute",
+ help,
);
}
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 919fa2140d5be..fc79c9232d1bd 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -779,16 +779,21 @@ impl RiscvInterruptKind {
/// Metadata describing how the arguments to a native function
/// should be passed in order to respect the native ABI.
///
+/// The signature represented by this type may not match the MIR function signature.
+/// Certain attributes, like `#[track_caller]` can introduce additional arguments, which are present in [`FnAbi`], but not in `FnSig`.
+/// While this difference is rarely relevant, it should still be kept in mind.
+///
/// I will do my best to describe this structure, but these
/// comments are reverse-engineered and may be inaccurate. -NDM
#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)]
pub struct FnAbi<'a, Ty> {
- /// The LLVM types of each argument.
+ /// The type, layout, and information about how each argument is passed.
pub args: Box<[ArgAbi<'a, Ty>]>,
- /// LLVM return type.
+ /// The layout, type, and the way a value is returned from this function.
pub ret: ArgAbi<'a, Ty>,
+ /// Marks this function as variadic (accepting a variable number of arguments).
pub c_variadic: bool,
/// The count of non-variadic arguments.
@@ -796,9 +801,9 @@ pub struct FnAbi<'a, Ty> {
/// Should only be different from args.len() when c_variadic is true.
/// This can be used to know whether an argument is variadic or not.
pub fixed_count: u32,
-
+ /// The calling convention of this function.
pub conv: Conv,
-
+ /// Indicates if an unwind may happen across a call to this function.
pub can_unwind: bool,
}
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 9a027d7f937ec..97bea28f06a3a 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -1,7 +1,7 @@
//! Code shared by trait and projection goals for candidate assembly.
use crate::solve::GoalSource;
-use crate::solve::{inspect, EvalCtxt, SolverMode};
+use crate::solve::{EvalCtxt, SolverMode};
use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution;
use rustc_middle::bug;
@@ -16,7 +16,6 @@ use rustc_middle::ty::{fast_reject, TypeFoldable};
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
use std::fmt::Debug;
-use std::mem;
pub(super) mod structural_traits;
@@ -792,17 +791,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
goal: Goal<'tcx, G>,
candidates: &mut Vec>,
) {
- // HACK: We temporarily remove the `ProofTreeBuilder` to
- // avoid adding `Trait` candidates to the candidates used
- // to prove the current goal.
- let inspect = mem::replace(&mut self.inspect, inspect::ProofTreeBuilder::new_noop());
-
let tcx = self.tcx();
let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> =
goal.with(tcx, goal.predicate.trait_ref(tcx));
- let mut trait_candidates_from_env = Vec::new();
- self.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env);
- self.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env);
+
+ let mut trait_candidates_from_env = vec![];
+ self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
+ ecx.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env);
+ ecx.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env);
+ });
+
if !trait_candidates_from_env.is_empty() {
let trait_env_result = self.merge_candidates(trait_candidates_from_env);
match trait_env_result.unwrap().value.certainty {
@@ -831,7 +829,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
}
}
- self.inspect = inspect;
}
/// If there are multiple ways to prove a trait or projection goal, we have
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index 6fda5f4af25e7..68c0c8bf09eac 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -176,7 +176,8 @@ fn to_selection<'tcx>(
| ProbeKind::UnsizeAssembly
| ProbeKind::UpcastProjectionCompatibility
| ProbeKind::OpaqueTypeStorageLookup { result: _ }
- | ProbeKind::Root { result: _ } => {
+ | ProbeKind::Root { result: _ }
+ | ProbeKind::ShadowedEnvProbing => {
span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind())
}
})
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index fd36b7ffd4eb4..b71a1b339cb81 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -18,8 +18,8 @@ use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{inspect, QueryResult};
use rustc_middle::traits::solve::{Certainty, Goal};
use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty;
use rustc_middle::ty::TypeFoldable;
+use rustc_middle::{bug, ty};
use rustc_span::{Span, DUMMY_SP};
use crate::solve::eval_ctxt::canonical;
@@ -290,12 +290,25 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
match *step {
inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
inspect::ProbeStep::NestedProbe(ref probe) => {
- // Nested probes have to prove goals added in their parent
- // but do not leak them, so we truncate the added goals
- // afterwards.
- let num_goals = nested_goals.len();
- self.candidates_recur(candidates, nested_goals, probe);
- nested_goals.truncate(num_goals);
+ match probe.kind {
+ // These never assemble candidates for the goal we're trying to solve.
+ inspect::ProbeKind::UpcastProjectionCompatibility
+ | inspect::ProbeKind::ShadowedEnvProbing => continue,
+
+ inspect::ProbeKind::NormalizedSelfTyAssembly
+ | inspect::ProbeKind::UnsizeAssembly
+ | inspect::ProbeKind::Root { .. }
+ | inspect::ProbeKind::TryNormalizeNonRigid { .. }
+ | inspect::ProbeKind::TraitCandidate { .. }
+ | inspect::ProbeKind::OpaqueTypeStorageLookup { .. } => {
+ // Nested probes have to prove goals added in their parent
+ // but do not leak them, so we truncate the added goals
+ // afterwards.
+ let num_goals = nested_goals.len();
+ self.candidates_recur(candidates, nested_goals, probe);
+ nested_goals.truncate(num_goals);
+ }
+ }
}
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
assert_eq!(shallow_certainty.replace(c), None);
@@ -308,9 +321,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
}
match probe.kind {
- inspect::ProbeKind::NormalizedSelfTyAssembly
- | inspect::ProbeKind::UnsizeAssembly
- | inspect::ProbeKind::UpcastProjectionCompatibility => (),
+ inspect::ProbeKind::UpcastProjectionCompatibility
+ | inspect::ProbeKind::ShadowedEnvProbing => bug!(),
+
+ inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly => {}
// We add a candidate even for the root evaluation if there
// is only one way to prove a given goal, e.g. for `WellFormed`.
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index c748cdf6ed278..af07e9ff96bf8 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -2,6 +2,7 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
+use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use std::fmt;
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
@@ -86,6 +87,46 @@ impl DebugWithInfcx for ConstKind {
}
}
+/// An unevaluated (potentially generic) constant used in the type-system.
+#[derive(derivative::Derivative)]
+#[derivative(
+ Clone(bound = ""),
+ Copy(bound = ""),
+ Hash(bound = ""),
+ PartialEq(bound = ""),
+ Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct UnevaluatedConst {
+ pub def: I::DefId,
+ pub args: I::GenericArgs,
+}
+
+impl UnevaluatedConst {
+ #[inline]
+ pub fn new(def: I::DefId, args: I::GenericArgs) -> UnevaluatedConst {
+ UnevaluatedConst { def, args }
+ }
+}
+
+impl fmt::Debug for UnevaluatedConst {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ WithInfcx::with_no_infcx(self).fmt(f)
+ }
+}
+impl DebugWithInfcx for UnevaluatedConst {
+ fn fmt>(
+ this: WithInfcx<'_, Infcx, &Self>,
+ f: &mut core::fmt::Formatter<'_>,
+ ) -> core::fmt::Result {
+ f.debug_struct("UnevaluatedConst")
+ .field("def", &this.data.def)
+ .field("args", &this.wrap(this.data.args))
+ .finish()
+ }
+}
+
rustc_index::newtype_index! {
/// A **`const`** **v**ariable **ID**.
#[encodable]
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 5e98163643893..92b1e08ab0a36 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -5,7 +5,8 @@ use std::ops::Deref;
use crate::fold::TypeSuperFoldable;
use crate::visit::{Flags, TypeSuperVisitable};
use crate::{
- BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind, TyKind, UniverseIndex,
+ AliasTy, AliasTyKind, BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind,
+ TyKind, UnevaluatedConst, UniverseIndex,
};
pub trait Ty>:
@@ -14,12 +15,15 @@ pub trait Ty>:
+ Hash
+ Eq
+ Into
+ + Into
+ IntoKind>
+ TypeSuperVisitable
+ TypeSuperFoldable
+ Flags
{
fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
+
+ fn new_alias(interner: I, kind: AliasTyKind, alias_ty: AliasTy) -> Self;
}
pub trait Region>:
@@ -36,6 +40,7 @@ pub trait Const>:
+ Hash
+ Eq
+ Into
+ + Into
+ IntoKind>
+ TypeSuperVisitable
+ TypeSuperFoldable
@@ -43,6 +48,8 @@ pub trait Const>:
{
fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
+ fn new_unevaluated(interner: I, uv: UnevaluatedConst, ty: I::Ty) -> Self;
+
fn ty(self) -> I::Ty;
}
@@ -89,21 +96,3 @@ pub trait BoundVars {
fn has_no_bound_vars(&self) -> bool;
}
-
-pub trait AliasTerm: Copy + DebugWithInfcx + Hash + Eq + Sized {
- fn new(
- interner: I,
- trait_def_id: I::DefId,
- args: impl IntoIterator>,
- ) -> Self;
-
- fn def_id(self) -> I::DefId;
-
- fn args(self) -> I::GenericArgs;
-
- fn trait_def_id(self, interner: I) -> I::DefId;
-
- fn self_ty(self) -> I::Ty;
-
- fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self;
-}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index af0e833b9e983..d6680977168ec 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -6,13 +6,16 @@ use crate::inherent::*;
use crate::ir_print::IrPrint;
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
use crate::{
- CanonicalVarInfo, CoercePredicate, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef,
- NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
+ AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate,
+ DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, NormalizesTo, ProjectionPredicate,
+ SubtypePredicate, TraitPredicate, TraitRef,
};
pub trait Interner:
Sized
+ Copy
+ + IrPrint>
+ + IrPrint>
+ IrPrint>
+ IrPrint>
+ IrPrint>
@@ -27,6 +30,7 @@ pub trait Interner:
type AdtDef: Copy + Debug + Hash + Eq;
type GenericArgs: GenericArgs;
+ type GenericArgsSlice: Copy + Debug + Hash + Eq;
type GenericArg: Copy + DebugWithInfcx + Hash + Eq;
type Term: Copy + Debug + Hash + Eq;
@@ -39,7 +43,6 @@ pub trait Interner:
// Kinds of tys
type Ty: Ty;
type Tys: Copy + Debug + Hash + Eq + IntoIterator
- ;
- type AliasTy: Copy + DebugWithInfcx + Hash + Eq + Sized;
type ParamTy: Copy + Debug + Hash + Eq;
type BoundTy: Copy + Debug + Hash + Eq;
type PlaceholderTy: PlaceholderLike;
@@ -74,7 +77,6 @@ pub trait Interner:
type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
type ProjectionPredicate: Copy + Debug + Hash + Eq;
- type AliasTerm: AliasTerm;
type NormalizesTo: Copy + Debug + Hash + Eq;
type SubtypePredicate: Copy + Debug + Hash + Eq;
type CoercePredicate: Copy + Debug + Hash + Eq;
@@ -86,8 +88,23 @@ pub trait Interner:
type GenericsOf: GenericsOf;
fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
+ // FIXME: Remove after uplifting `EarlyBinder`
+ fn type_of_instantiated(self, def_id: Self::DefId, args: Self::GenericArgs) -> Self::Ty;
+
+ fn alias_ty_kind(self, alias: AliasTy) -> AliasTyKind;
+
+ fn alias_term_kind(self, alias: AliasTerm) -> AliasTermKind;
+
+ fn trait_ref_and_own_args_for_alias(
+ self,
+ def_id: Self::DefId,
+ args: Self::GenericArgs,
+ ) -> (TraitRef, Self::GenericArgsSlice);
+
fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs;
+ fn mk_args_from_iter(self, args: impl Iterator
- ) -> Self::GenericArgs;
+
fn check_and_mk_args(
self,
def_id: Self::DefId,
diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs
index 5885139754afe..2a766d0bc09c9 100644
--- a/compiler/rustc_type_ir/src/ir_print.rs
+++ b/compiler/rustc_type_ir/src/ir_print.rs
@@ -1,8 +1,8 @@
use std::fmt;
use crate::{
- CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner, NormalizesTo,
- ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
+ AliasTerm, AliasTy, CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner,
+ NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
};
pub trait IrPrint {
@@ -43,6 +43,8 @@ define_display_via_print!(
NormalizesTo,
SubtypePredicate,
CoercePredicate,
+ AliasTy,
+ AliasTerm,
);
define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection);
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index 71f198d2b8e84..b6c7c2c348cca 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -6,7 +6,9 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen
use crate::inherent::*;
use crate::visit::TypeVisitableExt as _;
-use crate::{DebugWithInfcx, Interner};
+use crate::{
+ AliasTy, AliasTyKind, DebugWithInfcx, InferCtxtLike, Interner, UnevaluatedConst, WithInfcx,
+};
/// A complete reference to a trait. These take numerous guises in syntax,
/// but perhaps the most recognizable form is in a where-clause:
@@ -272,20 +274,20 @@ impl ExistentialProjection {
/// For example, if this is a projection of `exists T. ::Item == X`,
/// then this function would return an `exists T. T: Iterator` existential trait
/// reference.
- pub fn trait_ref(&self, tcx: I) -> ExistentialTraitRef {
- let def_id = tcx.parent(self.def_id);
- let args_count = tcx.generics_of(def_id).count() - 1;
- let args = tcx.mk_args(&self.args[..args_count]);
+ pub fn trait_ref(&self, interner: I) -> ExistentialTraitRef {
+ let def_id = interner.parent(self.def_id);
+ let args_count = interner.generics_of(def_id).count() - 1;
+ let args = interner.mk_args(&self.args[..args_count]);
ExistentialTraitRef { def_id, args }
}
- pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate {
+ pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate {
// otherwise the escaping regions would be captured by the binders
debug_assert!(!self_ty.has_escaping_bound_vars());
ProjectionPredicate {
- projection_term: I::AliasTerm::new(
- tcx,
+ projection_term: AliasTerm::new(
+ interner,
self.def_id,
[self_ty.into()].into_iter().chain(self.args),
),
@@ -293,13 +295,13 @@ impl ExistentialProjection {
}
}
- pub fn erase_self_ty(tcx: I, projection_predicate: ProjectionPredicate) -> Self {
+ pub fn erase_self_ty(interner: I, projection_predicate: ProjectionPredicate) -> Self {
// Assert there is a Self.
- projection_predicate.projection_term.args().type_at(0);
+ projection_predicate.projection_term.args.type_at(0);
Self {
- def_id: projection_predicate.projection_term.def_id(),
- args: tcx.mk_args(&projection_predicate.projection_term.args()[1..]),
+ def_id: projection_predicate.projection_term.def_id,
+ args: interner.mk_args(&projection_predicate.projection_term.args[1..]),
term: projection_predicate.term,
}
}
@@ -339,6 +341,190 @@ impl AliasTermKind {
}
}
+/// Represents the unprojected term of a projection goal.
+///
+/// * For a projection, this would be `>::N<...>`.
+/// * For an inherent projection, this would be `Ty::N<...>`.
+/// * For an opaque type, there is no explicit syntax.
+#[derive(derivative::Derivative)]
+#[derivative(
+ Clone(bound = ""),
+ Copy(bound = ""),
+ Hash(bound = ""),
+ PartialEq(bound = ""),
+ Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct AliasTerm {
+ /// The parameters of the associated or opaque item.
+ ///
+ /// For a projection, these are the generic parameters for the trait and the
+ /// GAT parameters, if there are any.
+ ///
+ /// For an inherent projection, they consist of the self type and the GAT parameters,
+ /// if there are any.
+ ///
+ /// For RPIT the generic parameters are for the generics of the function,
+ /// while for TAIT it is used for the generic parameters of the alias.
+ pub args: I::GenericArgs,
+
+ /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
+ /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
+ /// this is an opaque.
+ ///
+ /// During codegen, `interner.type_of(def_id)` can be used to get the type of the
+ /// underlying type if the type is an opaque.
+ ///
+ /// Note that if this is an associated type, this is not the `DefId` of the
+ /// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`,
+ /// aka. `interner.parent(def_id)`.
+ pub def_id: I::DefId,
+
+ /// This field exists to prevent the creation of `AliasTerm` without using
+ /// [AliasTerm::new].
+ _use_alias_term_new_instead: (),
+}
+
+impl std::fmt::Debug for AliasTerm {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ WithInfcx::with_no_infcx(self).fmt(f)
+ }
+}
+impl DebugWithInfcx for AliasTerm {
+ fn fmt>(
+ this: WithInfcx<'_, Infcx, &Self>,
+ f: &mut std::fmt::Formatter<'_>,
+ ) -> std::fmt::Result {
+ f.debug_struct("AliasTerm")
+ .field("args", &this.map(|data| data.args))
+ .field("def_id", &this.data.def_id)
+ .finish()
+ }
+}
+
+impl AliasTerm {
+ pub fn new(
+ interner: I,
+ def_id: I::DefId,
+ args: impl IntoIterator>,
+ ) -> AliasTerm {
+ let args = interner.check_and_mk_args(def_id, args);
+ AliasTerm { def_id, args, _use_alias_term_new_instead: () }
+ }
+
+ pub fn expect_ty(self, interner: I) -> AliasTy {
+ match self.kind(interner) {
+ AliasTermKind::ProjectionTy
+ | AliasTermKind::InherentTy
+ | AliasTermKind::OpaqueTy
+ | AliasTermKind::WeakTy => {}
+ AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
+ panic!("Cannot turn `UnevaluatedConst` into `AliasTy`")
+ }
+ }
+ AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
+ }
+
+ pub fn kind(self, interner: I) -> AliasTermKind {
+ interner.alias_term_kind(self)
+ }
+
+ pub fn to_term(self, interner: I) -> I::Term {
+ match self.kind(interner) {
+ AliasTermKind::ProjectionTy => Ty::new_alias(
+ interner,
+ AliasTyKind::Projection,
+ AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+ )
+ .into(),
+ AliasTermKind::InherentTy => Ty::new_alias(
+ interner,
+ AliasTyKind::Inherent,
+ AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+ )
+ .into(),
+ AliasTermKind::OpaqueTy => Ty::new_alias(
+ interner,
+ AliasTyKind::Opaque,
+ AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+ )
+ .into(),
+ AliasTermKind::WeakTy => Ty::new_alias(
+ interner,
+ AliasTyKind::Weak,
+ AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+ )
+ .into(),
+ AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
+ I::Const::new_unevaluated(
+ interner,
+ UnevaluatedConst::new(self.def_id, self.args),
+ interner.type_of_instantiated(self.def_id, self.args),
+ )
+ .into()
+ }
+ }
+ }
+}
+
+/// The following methods work only with (trait) associated type projections.
+impl AliasTerm {
+ pub fn self_ty(self) -> I::Ty {
+ self.args.type_at(0)
+ }
+
+ pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
+ AliasTerm::new(
+ interner,
+ self.def_id,
+ [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
+ )
+ }
+
+ pub fn trait_def_id(self, interner: I) -> I::DefId {
+ assert!(
+ matches!(
+ self.kind(interner),
+ AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst
+ ),
+ "expected a projection"
+ );
+ interner.parent(self.def_id)
+ }
+
+ /// Extracts the underlying trait reference and own args from this projection.
+ /// For example, if this is a projection of `::Item<'a>`,
+ /// then this function would return a `T: StreamingIterator` trait reference and
+ /// `['a]` as the own args.
+ pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef, I::GenericArgsSlice) {
+ interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
+ }
+
+ /// Extracts the underlying trait reference from this projection.
+ /// For example, if this is a projection of `::Item`,
+ /// then this function would return a `T: Iterator` trait reference.
+ ///
+ /// WARNING: This will drop the args for generic associated types
+ /// consider calling [Self::trait_ref_and_own_args] to get those
+ /// as well.
+ pub fn trait_ref(self, interner: I) -> TraitRef {
+ self.trait_ref_and_own_args(interner).0
+ }
+}
+
+impl From> for AliasTerm {
+ fn from(ty: AliasTy) -> Self {
+ AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
+ }
+}
+
+impl From> for AliasTerm {
+ fn from(ct: UnevaluatedConst) -> Self {
+ AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
+ }
+}
+
/// This kind of predicate has no *direct* correspondent in the
/// syntax, but it roughly corresponds to the syntactic forms:
///
@@ -362,7 +548,7 @@ impl AliasTermKind {
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct ProjectionPredicate {
- pub projection_term: I::AliasTerm,
+ pub projection_term: AliasTerm,
pub term: I::Term,
}
@@ -371,16 +557,16 @@ impl ProjectionPredicate {
self.projection_term.self_ty()
}
- pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate {
- Self { projection_term: self.projection_term.with_self_ty(tcx, self_ty), ..self }
+ pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate {
+ Self { projection_term: self.projection_term.with_self_ty(interner, self_ty), ..self }
}
- pub fn trait_def_id(self, tcx: I) -> I::DefId {
- self.projection_term.trait_def_id(tcx)
+ pub fn trait_def_id(self, interner: I) -> I::DefId {
+ self.projection_term.trait_def_id(interner)
}
pub fn def_id(self) -> I::DefId {
- self.projection_term.def_id()
+ self.projection_term.def_id
}
}
@@ -403,7 +589,7 @@ impl fmt::Debug for ProjectionPredicate {
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct NormalizesTo {
- pub alias: I::AliasTerm,
+ pub alias: AliasTerm,
pub term: I::Term,
}
@@ -412,16 +598,16 @@ impl NormalizesTo {
self.alias.self_ty()
}
- pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> NormalizesTo {
- Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
+ pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo {
+ Self { alias: self.alias.with_self_ty(interner, self_ty), ..self }
}
- pub fn trait_def_id(self, tcx: I) -> I::DefId {
- self.alias.trait_def_id(tcx)
+ pub fn trait_def_id(self, interner: I) -> I::DefId {
+ self.alias.trait_def_id(interner)
}
pub fn def_id(self) -> I::DefId {
- self.alias.def_id()
+ self.alias.def_id
}
}
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 6e544d0e6ace4..672c890f94edb 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -4,11 +4,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
-use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
+use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use std::fmt;
-use crate::Interner;
-use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
+use crate::inherent::*;
+use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, TraitRef, WithInfcx};
use self::TyKind::*;
@@ -88,7 +88,7 @@ pub enum TyKind {
/// for `struct List` and the args `[i32]`.
///
/// Note that generic parameters in fields only get lazily instantiated
- /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, args))`.
+ /// by using something like `adt_def.all_fields().map(|field| field.ty(interner, args))`.
Adt(I::AdtDef, I::GenericArgs),
/// An unsized FFI type that is opaque to Rust. Written as `extern type T`.
@@ -201,7 +201,7 @@ pub enum TyKind {
/// A projection, opaque type, weak type alias, or inherent associated type.
/// All of these types are represented as pairs of def-id and args, and can
/// be normalized, so they are grouped conceptually.
- Alias(AliasTyKind, I::AliasTy),
+ Alias(AliasTyKind, AliasTy),
/// A type parameter; for example, `T` in `fn f(x: T) {}`.
Param(I::ParamTy),
@@ -422,6 +422,154 @@ impl fmt::Debug for TyKind {
}
}
+/// Represents the projection of an associated, opaque, or lazy-type-alias type.
+///
+/// * For a projection, this would be `>::N<...>`.
+/// * For an inherent projection, this would be `Ty::N<...>`.
+/// * For an opaque type, there is no explicit syntax.
+#[derive(derivative::Derivative)]
+#[derivative(
+ Clone(bound = ""),
+ Copy(bound = ""),
+ Hash(bound = ""),
+ PartialEq(bound = ""),
+ Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct AliasTy {
+ /// The parameters of the associated or opaque type.
+ ///
+ /// For a projection, these are the generic parameters for the trait and the
+ /// GAT parameters, if there are any.
+ ///
+ /// For an inherent projection, they consist of the self type and the GAT parameters,
+ /// if there are any.
+ ///
+ /// For RPIT the generic parameters are for the generics of the function,
+ /// while for TAIT it is used for the generic parameters of the alias.
+ pub args: I::GenericArgs,
+
+ /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
+ /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
+ /// this is an opaque.
+ ///
+ /// During codegen, `interner.type_of(def_id)` can be used to get the type of the
+ /// underlying type if the type is an opaque.
+ ///
+ /// Note that if this is an associated type, this is not the `DefId` of the
+ /// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`,
+ /// aka. `interner.parent(def_id)`.
+ pub def_id: I::DefId,
+
+ /// This field exists to prevent the creation of `AliasTy` without using
+ /// [AliasTy::new].
+ pub(crate) _use_alias_ty_new_instead: (),
+}
+
+impl AliasTy {
+ pub fn new(
+ interner: I,
+ def_id: I::DefId,
+ args: impl IntoIterator>,
+ ) -> AliasTy {
+ let args = interner.check_and_mk_args(def_id, args);
+ AliasTy { def_id, args, _use_alias_ty_new_instead: () }
+ }
+
+ pub fn kind(self, interner: I) -> AliasTyKind {
+ interner.alias_ty_kind(self)
+ }
+
+ /// Whether this alias type is an opaque.
+ pub fn is_opaque(self, interner: I) -> bool {
+ matches!(self.kind(interner), AliasTyKind::Opaque)
+ }
+
+ pub fn to_ty(self, interner: I) -> I::Ty {
+ Ty::new_alias(interner, self.kind(interner), self)
+ }
+}
+
+/// The following methods work only with (trait) associated type projections.
+impl AliasTy {
+ pub fn self_ty(self) -> I::Ty {
+ self.args.type_at(0)
+ }
+
+ pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
+ AliasTy::new(
+ interner,
+ self.def_id,
+ [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
+ )
+ }
+
+ pub fn trait_def_id(self, interner: I) -> I::DefId {
+ assert_eq!(self.kind(interner), AliasTyKind::Projection, "expected a projection");
+ interner.parent(self.def_id)
+ }
+
+ /// Extracts the underlying trait reference and own args from this projection.
+ /// For example, if this is a projection of `::Item<'a>`,
+ /// then this function would return a `T: StreamingIterator` trait reference and
+ /// `['a]` as the own args.
+ pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef, I::GenericArgsSlice) {
+ debug_assert_eq!(self.kind(interner), AliasTyKind::Projection);
+ interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
+ }
+
+ /// Extracts the underlying trait reference from this projection.
+ /// For example, if this is a projection of `::Item`,
+ /// then this function would return a `T: Iterator` trait reference.
+ ///
+ /// WARNING: This will drop the args for generic associated types
+ /// consider calling [Self::trait_ref_and_own_args] to get those
+ /// as well.
+ pub fn trait_ref(self, interner: I) -> TraitRef {
+ self.trait_ref_and_own_args(interner).0
+ }
+}
+
+/// The following methods work only with inherent associated type projections.
+impl AliasTy {
+ /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that.
+ ///
+ /// Does the following transformation:
+ ///
+ /// ```text
+ /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
+ ///
+ /// I_i impl args
+ /// P_j GAT args
+ /// ```
+ pub fn rebase_inherent_args_onto_impl(
+ self,
+ impl_args: I::GenericArgs,
+ interner: I,
+ ) -> I::GenericArgs {
+ debug_assert_eq!(self.kind(interner), AliasTyKind::Inherent);
+ interner.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1)))
+ }
+}
+
+impl fmt::Debug for AliasTy {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ WithInfcx::with_no_infcx(self).fmt(f)
+ }
+}
+impl DebugWithInfcx for AliasTy {
+ fn fmt>(
+ this: WithInfcx<'_, Infcx, &Self>,
+ f: &mut core::fmt::Formatter<'_>,
+ ) -> core::fmt::Result {
+ f.debug_struct("AliasTy")
+ .field("args", &this.map(|data| data.args))
+ .field("def_id", &this.data.def_id)
+ .finish()
+ }
+}
+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum IntTy {
diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs
index c29e5565d514a..e9f4d0f93ed49 100644
--- a/library/core/src/ascii.rs
+++ b/library/core/src/ascii.rs
@@ -91,17 +91,21 @@ pub struct EscapeDefault(escape::EscapeIterInner<4>);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn escape_default(c: u8) -> EscapeDefault {
- let mut data = [Char::Null; 4];
- let range = escape::escape_ascii_into(&mut data, c);
- EscapeDefault(escape::EscapeIterInner::new(data, range))
+ EscapeDefault::new(c)
}
impl EscapeDefault {
+ #[inline]
+ pub(crate) const fn new(c: u8) -> Self {
+ Self(escape::EscapeIterInner::ascii(c))
+ }
+
+ #[inline]
pub(crate) fn empty() -> Self {
- let data = [Char::Null; 4];
- EscapeDefault(escape::EscapeIterInner::new(data, 0..0))
+ Self(escape::EscapeIterInner::empty())
}
+ #[inline]
pub(crate) fn as_str(&self) -> &str {
self.0.as_str()
}
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index a93b94867ce4c..458be49fb152a 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -449,10 +449,10 @@ impl char {
'\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark),
'\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe),
_ if args.escape_grapheme_extended && self.is_grapheme_extended() => {
- EscapeDebug::from_unicode(self.escape_unicode())
+ EscapeDebug::unicode(self)
}
_ if is_printable(self) => EscapeDebug::printable(self),
- _ => EscapeDebug::from_unicode(self.escape_unicode()),
+ _ => EscapeDebug::unicode(self),
}
}
@@ -555,9 +555,9 @@ impl char {
'\t' => EscapeDefault::backslash(ascii::Char::SmallT),
'\r' => EscapeDefault::backslash(ascii::Char::SmallR),
'\n' => EscapeDefault::backslash(ascii::Char::SmallN),
- '\\' | '\'' | '"' => EscapeDefault::backslash(self.as_ascii().unwrap()),
+ '\\' | '\'' | '\"' => EscapeDefault::backslash(self.as_ascii().unwrap()),
'\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()),
- _ => EscapeDefault::from_unicode(self.escape_unicode()),
+ _ => EscapeDefault::unicode(self),
}
}
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index a860c7c6aaadc..f3683fe3f9c83 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -152,10 +152,9 @@ pub const fn from_digit(num: u32, radix: u32) -> Option {
pub struct EscapeUnicode(escape::EscapeIterInner<10>);
impl EscapeUnicode {
- fn new(chr: char) -> Self {
- let mut data = [ascii::Char::Null; 10];
- let range = escape::escape_unicode_into(&mut data, chr);
- Self(escape::EscapeIterInner::new(data, range))
+ #[inline]
+ const fn new(c: char) -> Self {
+ Self(escape::EscapeIterInner::unicode(c))
}
}
@@ -219,18 +218,19 @@ impl fmt::Display for EscapeUnicode {
pub struct EscapeDefault(escape::EscapeIterInner<10>);
impl EscapeDefault {
- fn printable(chr: ascii::Char) -> Self {
- let data = [chr];
- Self(escape::EscapeIterInner::from_array(data))
+ #[inline]
+ const fn printable(c: ascii::Char) -> Self {
+ Self(escape::EscapeIterInner::ascii(c.to_u8()))
}
- fn backslash(chr: ascii::Char) -> Self {
- let data = [ascii::Char::ReverseSolidus, chr];
- Self(escape::EscapeIterInner::from_array(data))
+ #[inline]
+ const fn backslash(c: ascii::Char) -> Self {
+ Self(escape::EscapeIterInner::backslash(c))
}
- fn from_unicode(esc: EscapeUnicode) -> Self {
- Self(esc.0)
+ #[inline]
+ const fn unicode(c: char) -> Self {
+ Self(escape::EscapeIterInner::unicode(c))
}
}
@@ -304,23 +304,24 @@ enum EscapeDebugInner {
}
impl EscapeDebug {
- fn printable(chr: char) -> Self {
+ #[inline]
+ const fn printable(chr: char) -> Self {
Self(EscapeDebugInner::Char(chr))
}
- fn backslash(chr: ascii::Char) -> Self {
- let data = [ascii::Char::ReverseSolidus, chr];
- let iter = escape::EscapeIterInner::from_array(data);
- Self(EscapeDebugInner::Bytes(iter))
+ #[inline]
+ const fn backslash(c: ascii::Char) -> Self {
+ Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::backslash(c)))
}
- fn from_unicode(esc: EscapeUnicode) -> Self {
- Self(EscapeDebugInner::Bytes(esc.0))
+ #[inline]
+ const fn unicode(c: char) -> Self {
+ Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::unicode(c)))
}
+ #[inline]
fn clear(&mut self) {
- let bytes = escape::EscapeIterInner::from_array([]);
- self.0 = EscapeDebugInner::Bytes(bytes);
+ self.0 = EscapeDebugInner::Bytes(escape::EscapeIterInner::empty());
}
}
@@ -339,6 +340,7 @@ impl Iterator for EscapeDebug {
}
}
+ #[inline]
fn size_hint(&self) -> (usize, Option) {
let n = self.len();
(n, Some(n))
diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs
index 143e277283e2c..f6ec30b9f793a 100644
--- a/library/core/src/escape.rs
+++ b/library/core/src/escape.rs
@@ -6,56 +6,79 @@ use crate::ops::Range;
const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap();
-/// Escapes a byte into provided buffer; returns length of escaped
-/// representation.
-pub(crate) fn escape_ascii_into(output: &mut [ascii::Char; 4], byte: u8) -> Range {
- #[inline]
- fn backslash(a: ascii::Char) -> ([ascii::Char; 4], u8) {
- ([ascii::Char::ReverseSolidus, a, ascii::Char::Null, ascii::Char::Null], 2)
- }
+#[inline]
+const fn backslash(a: ascii::Char) -> ([ascii::Char; N], Range) {
+ const { assert!(N >= 2) };
+
+ let mut output = [ascii::Char::Null; N];
+
+ output[0] = ascii::Char::ReverseSolidus;
+ output[1] = a;
+
+ (output, 0..2)
+}
- let (data, len) = match byte {
+/// Escapes an ASCII character.
+///
+/// Returns a buffer and the length of the escaped representation.
+const fn escape_ascii(byte: u8) -> ([ascii::Char; N], Range) {
+ const { assert!(N >= 4) };
+
+ match byte {
b'\t' => backslash(ascii::Char::SmallT),
b'\r' => backslash(ascii::Char::SmallR),
b'\n' => backslash(ascii::Char::SmallN),
b'\\' => backslash(ascii::Char::ReverseSolidus),
b'\'' => backslash(ascii::Char::Apostrophe),
b'\"' => backslash(ascii::Char::QuotationMark),
- _ => {
- if let Some(a) = byte.as_ascii()
+ byte => {
+ let mut output = [ascii::Char::Null; N];
+
+ if let Some(c) = byte.as_ascii()
&& !byte.is_ascii_control()
{
- ([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1)
+ output[0] = c;
+ (output, 0..1)
} else {
- let hi = HEX_DIGITS[usize::from(byte >> 4)];
- let lo = HEX_DIGITS[usize::from(byte & 0xf)];
- ([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4)
+ let hi = HEX_DIGITS[(byte >> 4) as usize];
+ let lo = HEX_DIGITS[(byte & 0xf) as usize];
+
+ output[0] = ascii::Char::ReverseSolidus;
+ output[1] = ascii::Char::SmallX;
+ output[2] = hi;
+ output[3] = lo;
+
+ (output, 0..4)
}
}
- };
- *output = data;
- 0..len
+ }
}
-/// Escapes a character into provided buffer using `\u{NNNN}` representation.
-pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> Range {
+/// Escapes a character `\u{NNNN}` representation.
+///
+/// Returns a buffer and the length of the escaped representation.
+const fn escape_unicode(c: char) -> ([ascii::Char; N], Range) {
+ const { assert!(N >= 10 && N < u8::MAX as usize) };
+
+ let c = u32::from(c);
+
+ // OR-ing `1` ensures that for `c == 0` the code computes that
+ // one digit should be printed.
+ let start = (c | 1).leading_zeros() as usize / 4 - 2;
+
+ let mut output = [ascii::Char::Null; N];
+ output[3] = HEX_DIGITS[((c >> 20) & 15) as usize];
+ output[4] = HEX_DIGITS[((c >> 16) & 15) as usize];
+ output[5] = HEX_DIGITS[((c >> 12) & 15) as usize];
+ output[6] = HEX_DIGITS[((c >> 8) & 15) as usize];
+ output[7] = HEX_DIGITS[((c >> 4) & 15) as usize];
+ output[8] = HEX_DIGITS[((c >> 0) & 15) as usize];
output[9] = ascii::Char::RightCurlyBracket;
+ output[start + 0] = ascii::Char::ReverseSolidus;
+ output[start + 1] = ascii::Char::SmallU;
+ output[start + 2] = ascii::Char::LeftCurlyBracket;
- let ch = ch as u32;
- output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize];
- output[4] = HEX_DIGITS[((ch >> 16) & 15) as usize];
- output[5] = HEX_DIGITS[((ch >> 12) & 15) as usize];
- output[6] = HEX_DIGITS[((ch >> 8) & 15) as usize];
- output[7] = HEX_DIGITS[((ch >> 4) & 15) as usize];
- output[8] = HEX_DIGITS[((ch >> 0) & 15) as usize];
-
- // or-ing 1 ensures that for ch==0 the code computes that one digit should
- // be printed.
- let start = (ch | 1).leading_zeros() as usize / 4 - 2;
- const UNICODE_ESCAPE_PREFIX: &[ascii::Char; 3] = b"\\u{".as_ascii().unwrap();
- output[start..][..3].copy_from_slice(UNICODE_ESCAPE_PREFIX);
-
- (start as u8)..10
+ (output, (start as u8)..(N as u8))
}
/// An iterator over an fixed-size array.
@@ -65,45 +88,63 @@ pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> R
#[derive(Clone, Debug)]
pub(crate) struct EscapeIterInner {
// The element type ensures this is always ASCII, and thus also valid UTF-8.
- pub(crate) data: [ascii::Char; N],
+ data: [ascii::Char; N],
- // Invariant: alive.start <= alive.end <= N.
- pub(crate) alive: Range,
+ // Invariant: `alive.start <= alive.end <= N`
+ alive: Range,
}
impl EscapeIterInner {
- pub fn new(data: [ascii::Char; N], alive: Range) -> Self {
- const { assert!(N < 256) };
- debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}");
- Self { data, alive }
+ pub const fn backslash(c: ascii::Char) -> Self {
+ let (data, range) = backslash(c);
+ Self { data, alive: range }
+ }
+
+ pub const fn ascii(c: u8) -> Self {
+ let (data, range) = escape_ascii(c);
+ Self { data, alive: range }
}
- pub fn from_array(array: [ascii::Char; M]) -> Self {
- const { assert!(M <= N) };
+ pub const fn unicode(c: char) -> Self {
+ let (data, range) = escape_unicode(c);
+ Self { data, alive: range }
+ }
- let mut data = [ascii::Char::Null; N];
- data[..M].copy_from_slice(&array);
- Self::new(data, 0..M as u8)
+ #[inline]
+ pub const fn empty() -> Self {
+ Self { data: [ascii::Char::Null; N], alive: 0..0 }
}
+ #[inline]
pub fn as_ascii(&self) -> &[ascii::Char] {
- &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)]
+ // SAFETY: `self.alive` is guaranteed to be a valid range for indexing `self.data`.
+ unsafe {
+ self.data.get_unchecked(usize::from(self.alive.start)..usize::from(self.alive.end))
+ }
}
+ #[inline]
pub fn as_str(&self) -> &str {
self.as_ascii().as_str()
}
+ #[inline]
pub fn len(&self) -> usize {
usize::from(self.alive.end - self.alive.start)
}
pub fn next(&mut self) -> Option {
- self.alive.next().map(|i| self.data[usize::from(i)].to_u8())
+ let i = self.alive.next()?;
+
+ // SAFETY: `i` is guaranteed to be a valid index for `self.data`.
+ unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) }
}
pub fn next_back(&mut self) -> Option {
- self.alive.next_back().map(|i| self.data[usize::from(i)].to_u8())
+ let i = self.alive.next_back()?;
+
+ // SAFETY: `i` is guaranteed to be a valid index for `self.data`.
+ unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) }
}
pub fn advance_by(&mut self, n: usize) -> Result<(), NonZero> {
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 48a96c5792c64..446d0658c1262 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -584,11 +584,11 @@ macro_rules! uint_impl {
// Thus, rather than using `overflowing_sub` that produces a wrapping
// subtraction, check it ourself so we can use an unchecked one.
- if self >= rhs {
+ if self < rhs {
+ None
+ } else {
// SAFETY: just checked this can't overflow
Some(unsafe { intrinsics::unchecked_sub(self, rhs) })
- } else {
- None
}
}
diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs
index 993bf55edcf10..9014bb3782aba 100644
--- a/library/std/src/sys/pal/unix/alloc.rs
+++ b/library/std/src/sys/pal/unix/alloc.rs
@@ -87,21 +87,18 @@ cfg_if::cfg_if! {
// /memory/aligned_memory.cc
libc::memalign(layout.align(), layout.size()) as *mut u8
}
- } else if #[cfg(target_os = "wasi")] {
- #[inline]
- unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
- // C11 aligned_alloc requires that the size be a multiple of the alignment.
- // Layout already checks that the size rounded up doesn't overflow isize::MAX.
- let align = layout.align();
- let size = layout.size().next_multiple_of(align);
- libc::aligned_alloc(align, size) as *mut u8
- }
} else {
#[inline]
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
let mut out = ptr::null_mut();
- // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
- // Since these are all powers of 2, we can just use max.
+ // We prefer posix_memalign over aligned_malloc since with aligned_malloc,
+ // implementations are making almost arbitrary choices for which alignments are
+ // "supported", making it hard to use. For instance, some implementations require the
+ // size to be a multiple of the alignment (wasi emmalloc), while others require the
+ // alignment to be at least the pointer size (Illumos, macOS) -- which may or may not be
+ // standards-compliant, but that does not help us.
+ // posix_memalign only has one, clear requirement: that the alignment be a multiple of
+ // `sizeof(void*)`. Since these are all powers of 2, we can just use max.
let align = layout.align().max(crate::mem::size_of::());
let ret = libc::posix_memalign(&mut out, align, layout.size());
if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml
index d93c5fd25a150..fd2da24699086 100644
--- a/src/bootstrap/defaults/config.compiler.toml
+++ b/src/bootstrap/defaults/config.compiler.toml
@@ -8,6 +8,8 @@ compiler-docs = true
# where adding `debug!()` appears to do nothing.
# However, it makes running the compiler slightly slower.
debug-logging = true
+# Get actually-useful information from backtraces, profiling, etc. with minimal added bytes
+debuginfo-level = "line-tables-only"
# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
incremental = true
# Print backtrace on internal compiler errors during bootstrap
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 5bc9d7615e2bc..1f006e1453f4b 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -26,7 +26,9 @@ use crate::core::build_steps::tool::{self, Tool};
use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::core::config::TargetSelection;
use crate::utils::channel::{self, Info};
-use crate::utils::helpers::{exe, is_dylib, output, t, target_supports_cranelift_backend, timeit};
+use crate::utils::helpers::{
+ exe, is_dylib, move_file, output, t, target_supports_cranelift_backend, timeit,
+};
use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
@@ -2024,7 +2026,7 @@ impl Step for Extended {
builder.run(&mut cmd);
if !builder.config.dry_run() {
- t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
+ t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
}
}
}
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index a074d53aa36e6..60f48c5923e1c 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -12,7 +12,7 @@ use build_helper::ci::CiEnv;
use build_helper::stage0_parser::VersionMetadata;
use xz2::bufread::XzDecoder;
-use crate::utils::helpers::{check_run, exe, program_out_of_date};
+use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date};
use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode};
use crate::{t, Config};
@@ -209,7 +209,7 @@ impl Config {
None => panic!("no protocol in {url}"),
}
t!(
- std::fs::rename(&tempfile, dest_path),
+ move_file(&tempfile, dest_path),
format!("failed to rename {tempfile:?} to {dest_path:?}")
);
}
@@ -313,7 +313,7 @@ impl Config {
if src_path.is_dir() && dst_path.exists() {
continue;
}
- t!(fs::rename(src_path, dst_path));
+ t!(move_file(src_path, dst_path));
}
let dst_dir = dst.join(directory_prefix);
if dst_dir.exists() {
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index c3a03693f714f..a1c9ddebb5d96 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -180,4 +180,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Info,
summary: "New option `build.lldb` that will override the default lldb binary path used in debuginfo tests",
},
+ ChangeInfo {
+ change_id: 123337,
+ severity: ChangeSeverity::Info,
+ summary: r#"The compiler profile now defaults to rust.debuginfo-level = "line-tables-only""#,
+ },
];
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 0d2ff4f951b61..278359cb08e39 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -150,6 +150,21 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result<
}
}
+/// Rename a file if from and to are in the same filesystem or
+/// copy and remove the file otherwise
+pub fn move_file, Q: AsRef