1
Fork 0

Auto merge of #3154 - rust-lang:rustup-2023-11-04, r=RalfJung

Automatic Rustup
This commit is contained in:
bors 2023-11-04 08:10:57 +00:00
commit 1b2e4a9c94
770 changed files with 7340 additions and 6547 deletions

View file

@ -57,8 +57,9 @@ jobs:
os: ubuntu-20.04-4core-16gb
env: {}
- name: x86_64-gnu-llvm-15
env:
ENABLE_GCC_CODEGEN: "1"
os: ubuntu-20.04-16core-64gb
env: {}
- name: x86_64-gnu-tools
os: ubuntu-20.04-16core-64gb
env: {}

View file

@ -556,6 +556,7 @@ name = "clippy"
version = "0.1.75"
dependencies = [
"anstream",
"clippy_config",
"clippy_lints",
"clippy_utils",
"color-print",
@ -578,6 +579,16 @@ dependencies = [
"walkdir",
]
[[package]]
name = "clippy_config"
version = "0.1.75"
dependencies = [
"rustc-semver",
"serde",
"toml 0.7.5",
"walkdir",
]
[[package]]
name = "clippy_dev"
version = "0.0.1"
@ -597,6 +608,7 @@ version = "0.1.75"
dependencies = [
"arrayvec",
"cargo_metadata 0.15.4",
"clippy_config",
"clippy_utils",
"declare_clippy_lint",
"if_chain",
@ -621,10 +633,10 @@ name = "clippy_utils"
version = "0.1.75"
dependencies = [
"arrayvec",
"clippy_config",
"if_chain",
"itertools",
"rustc-semver",
"serde",
]
[[package]]
@ -2465,9 +2477,9 @@ dependencies = [
[[package]]
name = "minifier"
version = "0.2.3"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5394aa376422b4b2b6c02fd9cfcb657e4ec544ae98e43d7d5d785fd0d042fd6d"
checksum = "95bbbf96b9ac3482c2a25450b67a15ed851319bc5fabf3b40742ea9066e84282"
[[package]]
name = "minimal-lexical"
@ -3512,7 +3524,6 @@ dependencies = [
"rustc_span",
"rustc_target",
"thin-vec",
"tracing",
]
[[package]]
@ -3785,7 +3796,6 @@ dependencies = [
"rustc_monomorphize",
"rustc_parse",
"rustc_passes",
"rustc_plugin_impl",
"rustc_privacy",
"rustc_query_system",
"rustc_resolve",
@ -4074,7 +4084,6 @@ dependencies = [
"rustc_monomorphize",
"rustc_parse",
"rustc_passes",
"rustc_plugin_impl",
"rustc_privacy",
"rustc_query_impl",
"rustc_query_system",
@ -4384,21 +4393,6 @@ dependencies = [
"tracing",
]
[[package]]
name = "rustc_plugin_impl"
version = "0.0.0"
dependencies = [
"libloading 0.7.4",
"rustc_ast",
"rustc_errors",
"rustc_fluent_macro",
"rustc_lint",
"rustc_macros",
"rustc_metadata",
"rustc_session",
"rustc_span",
]
[[package]]
name = "rustc_privacy"
version = "0.0.0"

View file

@ -15,9 +15,10 @@ use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::definitions::DefPathData;
use rustc_session::errors::report_lit_error;
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::DUMMY_SP;
use rustc_span::{DesugaringKind, Span};
use thin_vec::{thin_vec, ThinVec};
impl<'hir> LoweringContext<'_, 'hir> {

View file

@ -16,9 +16,8 @@ use rustc_hir::PredicateOrigin;
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{Span, Symbol};
use rustc_span::{DesugaringKind, Span, Symbol};
use rustc_target::spec::abi;
use smallvec::{smallvec, SmallVec};
use thin_vec::ThinVec;

View file

@ -71,9 +71,8 @@ use rustc_middle::{
};
use rustc_session::parse::{add_feature_diagnostics, feature_err};
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_span::{DesugaringKind, Span, DUMMY_SP};
use smallvec::SmallVec;
use std::collections::hash_map::Entry;
use thin_vec::ThinVec;

View file

@ -19,5 +19,4 @@ rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
thin-vec = "0.2.12"
tracing = "0.1"
# tidy-alphabetical-end

View file

@ -1442,62 +1442,54 @@ fn deny_equality_constraints(
let mut err = errors::EqualityInWhere { span: predicate.span, assoc: None, assoc2: None };
// Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind {
if let TyKind::Path(None, path) = &qself.ty.kind {
match &path.segments[..] {
[PathSegment { ident, args: None, .. }] => {
for param in &generics.params {
if param.ident == *ident {
let param = ident;
match &full_path.segments[qself.position..] {
[PathSegment { ident, args, .. }] => {
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
let mut assoc_path = full_path.clone();
// Remove `Bar` from `Foo::Bar`.
assoc_path.segments.pop();
let len = assoc_path.segments.len() - 1;
let gen_args = args.as_deref().cloned();
// Build `<Bar = RhsTy>`.
let arg = AngleBracketedArg::Constraint(AssocConstraint {
id: rustc_ast::node_id::DUMMY_NODE_ID,
ident: *ident,
gen_args,
kind: AssocConstraintKind::Equality {
term: predicate.rhs_ty.clone().into(),
},
span: ident.span,
});
// Add `<Bar = RhsTy>` to `Foo`.
match &mut assoc_path.segments[len].args {
Some(args) => match args.deref_mut() {
GenericArgs::Parenthesized(_) => continue,
GenericArgs::AngleBracketed(args) => {
args.args.push(arg);
}
},
empty_args => {
*empty_args = Some(
AngleBracketedArgs {
span: ident.span,
args: thin_vec![arg],
}
.into(),
);
}
}
err.assoc = Some(errors::AssociatedSuggestion {
span: predicate.span,
ident: *ident,
param: *param,
path: pprust::path_to_string(&assoc_path),
})
}
_ => {}
};
if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind
&& let TyKind::Path(None, path) = &qself.ty.kind
&& let [PathSegment { ident, args: None, .. }] = &path.segments[..]
{
for param in &generics.params {
if param.ident == *ident
&& let [PathSegment { ident, args, .. }] = &full_path.segments[qself.position..]
{
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
let mut assoc_path = full_path.clone();
// Remove `Bar` from `Foo::Bar`.
assoc_path.segments.pop();
let len = assoc_path.segments.len() - 1;
let gen_args = args.as_deref().cloned();
// Build `<Bar = RhsTy>`.
let arg = AngleBracketedArg::Constraint(AssocConstraint {
id: rustc_ast::node_id::DUMMY_NODE_ID,
ident: *ident,
gen_args,
kind: AssocConstraintKind::Equality {
term: predicate.rhs_ty.clone().into(),
},
span: ident.span,
});
// Add `<Bar = RhsTy>` to `Foo`.
match &mut assoc_path.segments[len].args {
Some(args) => match args.deref_mut() {
GenericArgs::Parenthesized(_) => continue,
GenericArgs::AngleBracketed(args) => {
args.args.push(arg);
}
},
empty_args => {
*empty_args = Some(
AngleBracketedArgs {
span: ident.span,
args: thin_vec![arg],
}
.into(),
);
}
}
_ => {}
err.assoc = Some(errors::AssociatedSuggestion {
span: predicate.span,
ident: *ident,
param: param.ident,
path: pprust::path_to_string(&assoc_path),
})
}
}
}

View file

@ -10,53 +10,54 @@ use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::spec::abi;
use thin_vec::ThinVec;
use tracing::debug;
use crate::errors;
macro_rules! gate_feature_fn {
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
let (visitor, has_feature, span, name, explain, help) =
(&*$visitor, $has_feature, $span, $name, $explain, $help);
let has_feature: bool = has_feature(visitor.features);
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
if !has_feature && !span.allows_unstable($name) {
feature_err(&visitor.sess.parse_sess, name, span, explain).help(help).emit();
/// The common case.
macro_rules! gate {
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain).emit();
}
}};
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
let (visitor, has_feature, span, name, explain) =
(&*$visitor, $has_feature, $span, $name, $explain);
let has_feature: bool = has_feature(visitor.features);
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
if !has_feature && !span.allows_unstable($name) {
feature_err(&visitor.sess.parse_sess, name, span, explain).emit();
}
}};
(future_incompatible; $visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
let (visitor, has_feature, span, name, explain) =
(&*$visitor, $has_feature, $span, $name, $explain);
let has_feature: bool = has_feature(visitor.features);
debug!(
"gate_feature(feature = {:?}, span = {:?}); has? {} (future_incompatible)",
name, span, has_feature
);
if !has_feature && !span.allows_unstable($name) {
feature_warn(&visitor.sess.parse_sess, name, span, explain);
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain)
.help($help)
.emit();
}
}};
}
macro_rules! gate_feature_post {
($visitor: expr, $feature: ident, $span: expr, $explain: expr, $help: expr) => {
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain, $help)
};
($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
};
(future_incompatible; $visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
gate_feature_fn!(future_incompatible; $visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
};
/// The unusual case, where the `has_feature` condition is non-standard.
macro_rules! gate_alt {
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
if !$has_feature && !$span.allows_unstable($name) {
feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).emit();
}
}};
}
/// The case involving a multispan.
macro_rules! gate_multi {
($visitor:expr, $feature:ident, $spans:expr, $explain:expr) => {{
if !$visitor.features.$feature {
let spans: Vec<_> =
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
if !spans.is_empty() {
feature_err(&$visitor.sess.parse_sess, sym::$feature, spans, $explain).emit();
}
}
}};
}
/// The legacy case.
macro_rules! gate_legacy {
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
feature_warn(&$visitor.sess.parse_sess, sym::$feature, $span, $explain);
}
}};
}
pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
@ -78,7 +79,7 @@ impl<'a> PostExpansionVisitor<'a> {
match symbol_unescaped {
// Stable
sym::Rust | sym::C => {}
abi => gate_feature_post!(
abi => gate!(
&self,
const_extern_fn,
span,
@ -129,14 +130,14 @@ impl<'a> PostExpansionVisitor<'a> {
fn visit_ty(&mut self, ty: &ast::Ty) {
if let ast::TyKind::ImplTrait(..) = ty.kind {
if self.in_associated_ty {
gate_feature_post!(
gate!(
&self.vis,
impl_trait_in_assoc_type,
ty.span,
"`impl Trait` in associated types is unstable"
);
} else {
gate_feature_post!(
gate!(
&self.vis,
type_alias_impl_trait,
ty.span,
@ -153,23 +154,16 @@ impl<'a> PostExpansionVisitor<'a> {
fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
// Check only lifetime parameters are present and that the lifetime
// parameters that are present have no bounds.
let non_lt_param_spans: Vec<_> = params
.iter()
.filter_map(|param| match param.kind {
ast::GenericParamKind::Lifetime { .. } => None,
_ => Some(param.ident.span),
})
.collect();
// FIXME: gate_feature_post doesn't really handle multispans...
if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders {
feature_err(
&self.sess.parse_sess,
sym::non_lifetime_binders,
non_lt_param_spans,
crate::fluent_generated::ast_passes_forbidden_non_lifetime_param,
)
.emit();
}
let non_lt_param_spans = params.iter().filter_map(|param| match param.kind {
ast::GenericParamKind::Lifetime { .. } => None,
_ => Some(param.ident.span),
});
gate_multi!(
&self,
non_lifetime_binders,
non_lt_param_spans,
crate::fluent_generated::ast_passes_forbidden_non_lifetime_param
);
for param in params {
if !param.bounds.is_empty() {
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
@ -188,48 +182,39 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
..
}) = attr_info
{
gate_feature_fn!(self, has_feature, attr.span, *name, *descr);
gate_alt!(self, has_feature(&self.features), *name, attr.span, *descr);
}
// Check unstable flavors of the `#[doc]` attribute.
if attr.has_name(sym::doc) {
for nested_meta in attr.meta_item_list().unwrap_or_default() {
macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
$(if nested_meta.has_name(sym::$name) {
let msg = concat!("`#[doc(", stringify!($name), ")]` is experimental");
gate_feature_post!(self, $feature, attr.span, msg);
})*
macro_rules! gate_doc { ($($s:literal { $($name:ident => $feature:ident)* })*) => {
$($(if nested_meta.has_name(sym::$name) {
let msg = concat!("`#[doc(", stringify!($name), ")]` is ", $s);
gate!(self, $feature, attr.span, msg);
})*)*
}}
gate_doc!(
cfg => doc_cfg
cfg_hide => doc_cfg_hide
masked => doc_masked
notable_trait => doc_notable_trait
"experimental" {
cfg => doc_cfg
cfg_hide => doc_cfg_hide
masked => doc_masked
notable_trait => doc_notable_trait
}
"meant for internal use only" {
keyword => rustdoc_internals
fake_variadic => rustdoc_internals
}
);
if nested_meta.has_name(sym::keyword) {
let msg = "`#[doc(keyword)]` is meant for internal use only";
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
}
if nested_meta.has_name(sym::fake_variadic) {
let msg = "`#[doc(fake_variadic)]` is meant for internal use only";
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
}
}
}
if !attr.is_doc_comment()
&& attr.get_normal_item().path.segments.len() == 2
&& attr.get_normal_item().path.segments[0].ident.name == sym::diagnostic
&& let [seg, _] = attr.get_normal_item().path.segments.as_slice()
&& seg.ident.name == sym::diagnostic
&& !self.features.diagnostic_namespace
{
let msg = "`#[diagnostic]` attribute name space is experimental";
gate_feature_post!(
self,
diagnostic_namespace,
attr.get_normal_item().path.segments[0].ident.span,
msg
);
gate!(self, diagnostic_namespace, seg.ident.span, msg);
}
// Emit errors for non-staged-api crates.
@ -255,12 +240,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::ItemKind::Fn(..) => {
if attr::contains_name(&i.attrs, sym::start) {
gate_feature_post!(
gate!(
&self,
start,
i.span,
"`#[start]` functions are experimental \
and their signature may change \
"`#[start]` functions are experimental and their signature may change \
over time"
);
}
@ -270,7 +254,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
for attr in attr::filter_by_name(&i.attrs, sym::repr) {
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
if item.has_name(sym::simd) {
gate_feature_post!(
gate!(
&self,
repr_simd,
attr.span,
@ -283,7 +267,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, of_trait, .. }) => {
if let &ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!(
gate!(
&self,
negative_impls,
span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
@ -293,12 +277,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
if let ast::Defaultness::Default(_) = defaultness {
gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
gate!(&self, specialization, i.span, "specialization is unstable");
}
}
ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
gate_feature_post!(
gate!(
&self,
auto_traits,
i.span,
@ -307,12 +291,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
ast::ItemKind::TraitAlias(..) => {
gate_feature_post!(&self, trait_alias, i.span, "trait aliases are experimental");
gate!(&self, trait_alias, i.span, "trait aliases are experimental");
}
ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
let msg = "`macro` is experimental";
gate_feature_post!(&self, decl_macro, i.span, msg);
gate!(&self, decl_macro, i.span, msg);
}
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
@ -331,7 +315,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name);
let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm."));
if links_to_llvm {
gate_feature_post!(
gate!(
&self,
link_llvm_intrinsics,
i.span,
@ -340,7 +324,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
ast::ForeignItemKind::TyAlias(..) => {
gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
gate!(&self, extern_types, i.span, "extern types are experimental");
}
ast::ForeignItemKind::MacCall(..) => {}
}
@ -356,7 +340,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
}
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
gate!(&self, never_type, ty.span, "the `!` type is experimental");
}
_ => {}
}
@ -389,7 +373,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_expr(&mut self, e: &'a ast::Expr) {
match e.kind {
ast::ExprKind::TryBlock(_) => {
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
gate!(&self, try_blocks, e.span, "`try` expression is experimental");
}
_ => {}
}
@ -405,7 +389,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
_ => pat,
};
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
gate_feature_post!(
gate!(
&self,
half_open_range_patterns_in_slices,
pat.span,
@ -415,15 +399,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
PatKind::Box(..) => {
gate_feature_post!(
&self,
box_patterns,
pattern.span,
"box pattern syntax is experimental"
);
gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental");
}
PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => {
gate_feature_post!(
gate!(
&self,
exclusive_range_pattern,
pattern.span,
@ -451,7 +430,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
gate!(&self, c_variadic, span, "C-variadic functions are unstable");
}
visit::walk_fn(self, fn_kind)
@ -463,14 +442,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
&& args.inputs.is_empty()
&& matches!(args.output, ast::FnRetTy::Default(..))
{
gate_feature_post!(
gate!(
&self,
return_type_notation,
constraint.span,
"return type notation is experimental"
);
} else {
gate_feature_post!(
gate!(
&self,
associated_type_bounds,
constraint.span,
@ -486,7 +465,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::AssocItemKind::Fn(_) => true,
ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate_feature_post!(
gate!(
&self,
associated_type_defaults,
i.span,
@ -502,11 +481,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
};
if let ast::Defaultness::Default(_) = i.kind.defaultness() {
// Limit `min_specialization` to only specializing functions.
gate_feature_fn!(
gate_alt!(
&self,
|x: &Features| x.specialization || (is_fn && x.min_specialization),
i.span,
self.features.specialization || (is_fn && self.features.min_specialization),
sym::specialization,
i.span,
"specialization is unstable"
);
}
@ -521,17 +500,17 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
let spans = sess.parse_sess.gated_spans.spans.borrow();
macro_rules! gate_all {
($gate:ident, $msg:literal, $help:literal) => {
if let Some(spans) = spans.get(&sym::$gate) {
for span in spans {
gate_feature_post!(&visitor, $gate, *span, $msg, $help);
}
}
};
($gate:ident, $msg:literal) => {
if let Some(spans) = spans.get(&sym::$gate) {
for span in spans {
gate_feature_post!(&visitor, $gate, *span, $msg);
gate!(&visitor, $gate, *span, $msg);
}
}
};
($gate:ident, $msg:literal, $help:literal) => {
if let Some(spans) = spans.get(&sym::$gate) {
for span in spans {
gate!(&visitor, $gate, *span, $msg, $help);
}
}
};
@ -556,7 +535,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
for &span in spans.get(&sym::yield_expr).iter().copied().flatten() {
if !span.at_least_rust_2024() {
gate_feature_post!(&visitor, coroutines, span, "yield syntax is experimental");
gate!(&visitor, coroutines, span, "yield syntax is experimental");
}
}
gate_all!(gen_blocks, "gen blocks are experimental");
@ -590,7 +569,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
macro_rules! gate_all_legacy_dont_use {
($gate:ident, $msg:literal) => {
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg);
gate_legacy!(&visitor, $gate, *span, $msg);
}
};
}

View file

@ -9,9 +9,8 @@ use rustc_middle::{
hir::place::PlaceBase,
mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
};
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{sym, BytePos, Span};
use rustc_span::{sym, BytePos, DesugaringKind, Span};
use rustc_target::abi::FieldIdx;
use crate::diagnostics::BorrowedContentSource;

View file

@ -6,8 +6,8 @@ use crate::Upvar;
use rustc_index::IndexSlice;
use rustc_middle::mir::{Body, Local};
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn get_var_name_and_span_for_region(

View file

@ -6,9 +6,10 @@ pub use Ty::*;
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
use rustc_expand::base::ExtCtxt;
use rustc_span::source_map::{respan, DUMMY_SP};
use rustc_span::source_map::respan;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::Span;
use rustc_span::DUMMY_SP;
use thin_vec::ThinVec;
/// A path, e.g., `::std::option::Option::<i32>` (global). Has support

View file

@ -68,7 +68,6 @@ rm -r tests/run-make/split-debuginfo # same
rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported
rm -r tests/run-make/target-specs # i686 not supported by Cranelift
rm -r tests/run-make/mismatching-target-triples # same
rm -r tests/run-make/use-extern-for-plugins # same
rm tests/ui/asm/x86_64/issue-82869.rs # vector regs in inline asm not yet supported
rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly

View file

@ -18,7 +18,6 @@ path = "tests/lang_tests_release.rs"
harness = false
[features]
default = ["master"]
master = ["gccjit/master"]
[dependencies]

View file

@ -25,7 +25,7 @@ else
exit 1
fi
HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
HOST_TRIPLE=$($RUSTC -vV | grep host | cut -d: -f2 | tr -d " ")
# TODO: remove $OVERWRITE_TARGET_TRIPLE when config.sh is removed.
TARGET_TRIPLE="${OVERWRITE_TARGET_TRIPLE:-$HOST_TRIPLE}"
@ -54,6 +54,10 @@ if [[ -z "$BUILTIN_BACKEND" ]]; then
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
else
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=gcc $TEST_FLAGS -Cpanic=abort"
if [[ ! -z "$RUSTC_SYSROOT" ]]; then
export RUSTFLAGS="$RUSTFLAGS --sysroot $RUSTC_SYSROOT"
fi
fi
# FIXME(antoyo): remove once the atomic shim is gone

View file

@ -18,7 +18,7 @@ extern "C" {
}
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
core::intrinsics::abort();
}

View file

@ -3,7 +3,6 @@
#![no_std]
#![feature(allocator_api, rustc_private)]
#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values.
@ -48,7 +47,18 @@ mod realloc_fallback {
}
#[cfg(any(unix, target_os = "redox"))]
mod platform {
extern crate libc;
mod libc {
use core::ffi::{c_void, c_int};
#[link(name = "c")]
extern "C" {
pub fn malloc(size: usize) -> *mut c_void;
pub fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void;
pub fn calloc(nmemb: usize, size: usize) -> *mut c_void;
pub fn free(ptr: *mut u8);
pub fn posix_memalign(memptr: *mut *mut c_void, alignment: usize, size: usize) -> c_int;
}
}
use core::ptr;
use MIN_ALIGN;
use System;
@ -82,12 +92,12 @@ mod platform {
}
#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
libc::free(ptr as *mut libc::c_void)
libc::free(ptr as *mut _)
}
#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
libc::realloc(ptr as *mut _, new_size) as *mut u8
} else {
self.realloc_fallback(ptr, layout, new_size)
}

View file

@ -6,7 +6,7 @@
extern {}
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
core::intrinsics::abort();
}

View file

@ -26,8 +26,8 @@ use rustc_middle::{bug, span_bug};
use rustc_session::config::{BranchProtection, CFGuard, CFProtection};
use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet};
use rustc_session::Session;
use rustc_span::source_map::Span;
use rustc_span::source_map::Spanned;
use rustc_span::Span;
use rustc_target::abi::{
call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
};

View file

@ -17,8 +17,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty};
use rustc_session::config::OptLevel;
use rustc_span::source_map::Span;
use rustc_span::{sym, Symbol};
use rustc_span::{sym, Span, Symbol};
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
use rustc_target::abi::{self, HasDataLayout, WrappingRange};
use rustc_target::spec::abi::Abi;

View file

@ -13,7 +13,7 @@ use rustc_middle::ty::cast::{CastTy, IntTy};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, Ty, TyCtxt};
use rustc_session::config::OptLevel;
use rustc_span::source_map::{Span, DUMMY_SP};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{self, FIRST_VARIANT};
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

View file

@ -10,7 +10,7 @@ use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::source_map::Span;
use rustc_span::Span;
use rustc_target::abi::{self, Abi};
use super::{CanAccessStatics, CompileTimeEvalContext, CompileTimeInterpreter};
@ -106,10 +106,16 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>(
}
/// This function converts an interpreter value into a MIR constant.
///
/// The `for_diagnostics` flag turns the usual rules for returning `ConstValue::Scalar` into a
/// best-effort attempt. This is not okay for use in const-eval sine it breaks invariants rustc
/// relies on, but it is okay for diagnostics which will just give up gracefully when they
/// encounter an `Indirect` they cannot handle.
#[instrument(skip(ecx), level = "debug")]
pub(super) fn op_to_const<'tcx>(
ecx: &CompileTimeEvalContext<'_, 'tcx>,
op: &OpTy<'tcx>,
for_diagnostics: bool,
) -> ConstValue<'tcx> {
// Handle ZST consistently and early.
if op.layout.is_zst() {
@ -133,7 +139,13 @@ pub(super) fn op_to_const<'tcx>(
_ => false,
};
let immediate = if force_as_immediate {
Right(ecx.read_immediate(op).expect("normalization works on validated constants"))
match ecx.read_immediate(op) {
Ok(imm) => Right(imm),
Err(err) if !for_diagnostics => {
panic!("normalization works on validated constants: {err:?}")
}
_ => op.as_mplace_or_imm(),
}
} else {
op.as_mplace_or_imm()
};
@ -205,7 +217,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
);
// Turn this into a proper constant.
op_to_const(&ecx, &mplace.into())
op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false)
}
#[instrument(skip(tcx), level = "debug")]

View file

@ -6,7 +6,7 @@ use rustc_middle::mir;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::source_map::DUMMY_SP;
use rustc_span::DUMMY_SP;
mod error;
mod eval_queries;
@ -72,7 +72,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
}
#[instrument(skip(tcx), level = "debug")]
pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>(
pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
tcx: TyCtxtAt<'tcx>,
val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>,
@ -99,7 +99,7 @@ pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>(
let fields_iter = (0..field_count)
.map(|i| {
let field_op = ecx.project_field(&down, i).ok()?;
let val = op_to_const(&ecx, &field_op);
let val = op_to_const(&ecx, &field_op, /* for diagnostics */ true);
Some((val, field_op.layout.ty))
})
.collect::<Option<Vec<_>>>()?;

View file

@ -10,7 +10,7 @@ use crate::interpret::{
use rustc_middle::mir;
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_span::source_map::DUMMY_SP;
use rustc_span::DUMMY_SP;
use rustc_target::abi::VariantIdx;
#[instrument(skip(ecx), level = "debug")]
@ -232,7 +232,7 @@ pub fn valtree_to_const_value<'tcx>(
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No);
let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty);
let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap());
op_to_const(&ecx, &imm.into())
op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
}
ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => {
let layout = tcx.layout_of(param_env_ty).unwrap();
@ -265,7 +265,7 @@ pub fn valtree_to_const_value<'tcx>(
dump_place(&ecx, &place);
intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &place).unwrap();
op_to_const(&ecx, &place.into())
op_to_const(&ecx, &place.into(), /* for diagnostics */ false)
}
ty::Never
| ty::Error(_)

View file

@ -145,16 +145,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert!(dest.layout.is_sized());
assert_eq!(cast_ty, dest.layout.ty); // we otherwise ignore `cast_ty` enirely...
if src.layout.size != dest.layout.size {
let src_bytes = src.layout.size.bytes();
let dest_bytes = dest.layout.size.bytes();
let src_ty = format!("{}", src.layout.ty);
let dest_ty = format!("{}", dest.layout.ty);
throw_ub_custom!(
fluent::const_eval_invalid_transmute,
src_bytes = src_bytes,
dest_bytes = dest_bytes,
src = src_ty,
dest = dest_ty,
src_bytes = src.layout.size.bytes(),
dest_bytes = dest.layout.size.bytes(),
src = src.layout.ty,
dest = dest.layout.ty,
);
}

View file

@ -54,8 +54,8 @@ pub fn provide(providers: &mut Providers) {
let (param_env, raw) = param_env_and_value.into_parts();
const_eval::eval_to_valtree(tcx, param_env, raw)
};
providers.hooks.try_destructure_mir_constant_for_diagnostics =
const_eval::try_destructure_mir_constant_for_diagnostics;
providers.hooks.try_destructure_mir_constant_for_user_output =
const_eval::try_destructure_mir_constant_for_user_output;
providers.valtree_to_const_val = |tcx, (ty, valtree)| {
const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree)
};

View file

@ -39,7 +39,6 @@ rustc_mir_transform = { path = "../rustc_mir_transform" }
rustc_monomorphize = { path = "../rustc_monomorphize" }
rustc_parse = { path = "../rustc_parse" }
rustc_passes = { path = "../rustc_passes" }
rustc_plugin_impl = { path = "../rustc_plugin_impl" }
rustc_privacy = { path = "../rustc_privacy" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_resolve = { path = "../rustc_resolve" }

View file

@ -20,8 +20,6 @@
#[macro_use]
extern crate tracing;
pub extern crate rustc_plugin_impl as plugin;
use rustc_ast as ast;
use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
use rustc_data_structures::profiling::{
@ -43,8 +41,9 @@ use rustc_session::cstore::MetadataLoader;
use rustc_session::getopts::{self, Matches};
use rustc_session::lint::{Lint, LintId};
use rustc_session::{config, EarlyErrorHandler, Session};
use rustc_span::source_map::{FileLoader, FileName};
use rustc_span::source_map::FileLoader;
use rustc_span::symbol::sym;
use rustc_span::FileName;
use rustc_target::json::ToJson;
use rustc_target::spec::{Target, TargetTriple};
@ -131,7 +130,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
rustc_monomorphize::DEFAULT_LOCALE_RESOURCE,
rustc_parse::DEFAULT_LOCALE_RESOURCE,
rustc_passes::DEFAULT_LOCALE_RESOURCE,
rustc_plugin_impl::DEFAULT_LOCALE_RESOURCE,
rustc_privacy::DEFAULT_LOCALE_RESOURCE,
rustc_query_system::DEFAULT_LOCALE_RESOURCE,
rustc_resolve::DEFAULT_LOCALE_RESOURCE,
@ -993,16 +991,14 @@ the command line flag directly.
}
/// Write to stdout lint command options, together with a list of all available lints
pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_lints: bool) {
safe_println!(
"
Available lint options:
-W <foo> Warn about <foo>
-A <foo> \
Allow <foo>
-A <foo> Allow <foo>
-D <foo> Deny <foo>
-F <foo> Forbid <foo> \
(deny <foo> and all attempts to override)
-F <foo> Forbid <foo> (deny <foo> and all attempts to override)
"
);
@ -1021,18 +1017,18 @@ Available lint options:
lints
}
let (plugin, builtin): (Vec<_>, _) =
lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_plugin);
let plugin = sort_lints(sess, plugin);
let (loaded, builtin): (Vec<_>, _) =
lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_loaded);
let loaded = sort_lints(sess, loaded);
let builtin = sort_lints(sess, builtin);
let (plugin_groups, builtin_groups): (Vec<_>, _) =
let (loaded_groups, builtin_groups): (Vec<_>, _) =
lint_store.get_lint_groups().partition(|&(.., p)| p);
let plugin_groups = sort_lint_groups(plugin_groups);
let loaded_groups = sort_lint_groups(loaded_groups);
let builtin_groups = sort_lint_groups(builtin_groups);
let max_name_len =
plugin.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
loaded.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
let padded = |x: &str| {
let mut s = " ".repeat(max_name_len - x.chars().count());
s.push_str(x);
@ -1060,7 +1056,7 @@ Available lint options:
let max_name_len = max(
"warnings".len(),
plugin_groups
loaded_groups
.iter()
.chain(&builtin_groups)
.map(|&(s, _)| s.chars().count())
@ -1098,20 +1094,22 @@ Available lint options:
print_lint_groups(builtin_groups, true);
match (loaded_plugins, plugin.len(), plugin_groups.len()) {
match (loaded_lints, loaded.len(), loaded_groups.len()) {
(false, 0, _) | (false, _, 0) => {
safe_println!("Lint tools like Clippy can provide additional lints and lint groups.");
safe_println!("Lint tools like Clippy can load additional lints and lint groups.");
}
(false, ..) => panic!("didn't load additional lints but got them anyway!"),
(true, 0, 0) => {
safe_println!("This crate does not load any additional lints or lint groups.")
}
(false, ..) => panic!("didn't load lint plugins but got them anyway!"),
(true, 0, 0) => safe_println!("This crate does not load any lint plugins or lint groups."),
(true, l, g) => {
if l > 0 {
safe_println!("Lint checks provided by plugins loaded by this crate:\n");
print_lints(plugin);
safe_println!("Lint checks loaded by this crate:\n");
print_lints(loaded);
}
if g > 0 {
safe_println!("Lint groups provided by plugins loaded by this crate:\n");
print_lint_groups(plugin_groups, false);
safe_println!("Lint groups loaded by this crate:\n");
print_lint_groups(loaded_groups, false);
}
}
}
@ -1128,7 +1126,7 @@ pub fn describe_flag_categories(handler: &EarlyErrorHandler, matches: &Matches)
rustc_errors::FatalError.raise();
}
// Don't handle -W help here, because we might first load plugins.
// Don't handle -W help here, because we might first load additional lints.
let debug_flags = matches.opt_strs("Z");
if debug_flags.iter().any(|x| *x == "help") {
describe_debug_flags();

View file

@ -1,3 +1,5 @@
#### Note: this error code is no longer emitted by the compiler`
Plugin `..` only found in rlib format, but must be available in dylib format.
Erroneous code example:

View file

@ -1,16 +1,13 @@
A plugin/crate was declared but cannot be found.
A crate was declared but cannot be found.
Erroneous code example:
```compile_fail,E0463
#![feature(plugin)]
#![plugin(cookie_monster)] // error: can't find crate for `cookie_monster`
extern crate cake_is_a_lie; // error: can't find crate for `cake_is_a_lie`
extern crate foo; // error: can't find crate
```
You need to link your code to the relevant crate in order to be able to use it
(through Cargo or the `-L` option of rustc example). Plugins are crates as
well, and you link to them the same way.
(through Cargo or the `-L` option of rustc, for example).
## Common causes

View file

@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.
The `plugin` attribute was malformed.
Erroneous code example:
```compile_fail,E0498
```ignore (E0498 is no longer emitted)
#![feature(plugin)]
#![plugin(foo(args))] // error: invalid argument
#![plugin(bar="test")] // error: invalid argument

View file

@ -4,8 +4,8 @@ use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
use rustc_ast::token::Delimiter;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::Ident;
use rustc_span::DUMMY_SP;
use smallvec::{smallvec, SmallVec};
use thin_vec::ThinVec;

View file

@ -2,7 +2,7 @@ use rustc_ast as ast;
use rustc_ast::tokenstream::TokenStream;
use rustc_parse::{new_parser_from_source_str, parser::Parser, source_file_to_stream};
use rustc_session::parse::ParseSess;
use rustc_span::create_default_session_if_not_set_then;
use rustc_span::create_default_session_globals_then;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::{BytePos, Span};
@ -181,7 +181,7 @@ impl<T: Write> Write for Shared<T> {
}
fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &str) {
create_default_session_if_not_set_then(|_| {
create_default_session_globals_then(|| {
let (handler, source_map, output) = create_test_handler();
source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());

View file

@ -417,24 +417,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
naked_functions, experimental!(naked)
),
// Plugins:
BuiltinAttribute {
name: sym::plugin,
only_local: false,
type_: CrateLevel,
template: template!(List: "name"),
duplicates: DuplicatesOk,
gate: Gated(
Stability::Deprecated(
"https://github.com/rust-lang/rust/pull/64675",
Some("may be removed in a future compiler version"),
),
sym::plugin,
"compiler plugins are deprecated",
cfg_fn!(plugin)
),
},
// Testing:
gated!(
test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, custom_test_frameworks,

View file

@ -152,9 +152,12 @@ declare_features! (
Some("removed in favor of `#![feature(marker_trait_attr)]`")),
(removed, panic_implementation, "1.28.0", Some(44489), None,
Some("subsumed by `#[panic_handler]`")),
/// Allows using `#![plugin(myplugin)]`.
(removed, plugin, "CURRENT_RUSTC_VERSION", Some(29597), None,
Some("plugins are no longer supported")),
/// Allows using `#[plugin_registrar]` on functions.
(removed, plugin_registrar, "1.54.0", Some(29597), None,
Some("a __rustc_plugin_registrar symbol must now be defined instead")),
Some("plugins are no longer supported")),
(removed, proc_macro_expr, "1.27.0", Some(54727), None,
Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
(removed, proc_macro_gen, "1.27.0", Some(54727), None,

View file

@ -528,8 +528,6 @@ declare_features! (
(unstable, object_safe_for_dispatch, "1.40.0", Some(43561), None),
/// Allows using `#[optimize(X)]`.
(unstable, optimize_attribute, "1.34.0", Some(54882), None),
/// Allows using `#![plugin(myplugin)]`.
(unstable, plugin, "1.0.0", Some(29597), None),
/// Allows exhaustive integer pattern matching on `usize` and `isize`.
(unstable, precise_pointer_size_matching, "1.32.0", Some(56354), None),
/// Allows macro attributes on expressions, statements and non-inline modules.

View file

@ -2,7 +2,7 @@ use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
use rustc_data_structures::stable_hasher::Hash64;
use rustc_span::def_id::{DefPathHash, StableCrateId};
use rustc_span::edition::Edition;
use rustc_span::{create_session_if_not_set_then, Symbol};
use rustc_span::{create_session_globals_then, Symbol};
#[test]
fn def_path_hash_depends_on_crate_id() {
@ -14,7 +14,7 @@ fn def_path_hash_depends_on_crate_id() {
// the crate by changing the crate disambiguator (e.g. via bumping the
// crate's version number).
create_session_if_not_set_then(Edition::Edition2024, |_| {
create_session_globals_then(Edition::Edition2024, || {
let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], "");
let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], "");

View file

@ -2162,128 +2162,10 @@ pub(super) fn check_type_bounds<'tcx>(
impl_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let param_env = tcx.param_env(impl_ty.def_id);
let container_id = impl_ty.container_id(tcx);
// Given
//
// impl<A, B> Foo<u32> for (A, B) {
// type Bar<C> = Wrapper<A, B, C>
// }
//
// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
// - `normalize_impl_ty_args` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
// - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
// - `rebased_args` would be `[(A, B), u32, ^0.0]`, combining the args from
// the *trait* with the generic associated type parameters (as bound vars).
//
// A note regarding the use of bound vars here:
// Imagine as an example
// ```
// trait Family {
// type Member<C: Eq>;
// }
//
// impl Family for VecFamily {
// type Member<C: Eq> = i32;
// }
// ```
// Here, we would generate
// ```notrust
// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) }
// ```
// when we really would like to generate
// ```notrust
// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) }
// ```
// But, this is probably fine, because although the first clause can be used with types C that
// do not implement Eq, for it to cause some kind of problem, there would have to be a
// VecFamily::Member<X> for some type X where !(X: Eq), that appears in the value of type
// Member<C: Eq> = .... That type would fail a well-formedness check that we ought to be doing
// elsewhere, which would check that any <T as Family>::Member<X> meets the bounds declared in
// the trait (notably, that X: Eq and T: Family).
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
// Extend the impl's identity args with late-bound GAT vars
let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id).extend_to(
tcx,
impl_ty.def_id,
|param, _| match param.kind {
GenericParamDefKind::Type { .. } => {
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
Ty::new_bound(
tcx,
ty::INNERMOST,
ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
)
.into()
}
GenericParamDefKind::Lifetime => {
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Region(kind);
bound_vars.push(bound_var);
ty::Region::new_late_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
)
.into()
}
GenericParamDefKind::Const { .. } => {
let bound_var = ty::BoundVariableKind::Const;
bound_vars.push(bound_var);
ty::Const::new_bound(
tcx,
ty::INNERMOST,
ty::BoundVar::from_usize(bound_vars.len() - 1),
tcx.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
)
.into()
}
},
);
// When checking something like
//
// trait X { type Y: PartialEq<<Self as X>::Y> }
// impl X for T { default type Y = S; }
//
// We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case
// we want <T as X>::Y to normalize to S. This is valid because we are
// checking the default value specifically here. Add this equality to the
// ParamEnv for normalization specifically.
let normalize_impl_ty = tcx.type_of(impl_ty.def_id).instantiate(tcx, normalize_impl_ty_args);
let rebased_args = normalize_impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
let normalize_param_env = {
let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
match normalize_impl_ty.kind() {
ty::Alias(ty::Projection, proj)
if proj.def_id == trait_ty.def_id && proj.args == rebased_args =>
{
// Don't include this predicate if the projected type is
// exactly the same as the projection. This can occur in
// (somewhat dubious) code like this:
//
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
}
_ => predicates.push(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
projection_ty: ty::AliasTy::new(tcx, trait_ty.def_id, rebased_args),
term: normalize_impl_ty.into(),
},
bound_vars,
)
.to_predicate(tcx),
),
};
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
};
debug!(?normalize_param_env);
let param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
debug!(?param_env);
let container_id = impl_ty.container_id(tcx);
let impl_ty_def_id = impl_ty.def_id.expect_local();
let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
@ -2336,8 +2218,7 @@ pub(super) fn check_type_bounds<'tcx>(
debug!("check_type_bounds: item_bounds={:?}", obligations);
for mut obligation in util::elaborate(tcx, obligations) {
let normalized_predicate =
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
let normalized_predicate = ocx.normalize(&normalize_cause, param_env, obligation.predicate);
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
obligation.predicate = normalized_predicate;
@ -2358,6 +2239,171 @@ pub(super) fn check_type_bounds<'tcx>(
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
}
/// Install projection predicates that allow GATs to project to their own
/// definition types. This is not allowed in general in cases of default
/// associated types in trait definitions, or when specialization is involved,
/// but is needed when checking these definition types actually satisfy the
/// trait bounds of the GAT.
///
/// # How it works
///
/// ```ignore (example)
/// impl<A, B> Foo<u32> for (A, B) {
/// type Bar<C> = Wrapper<A, B, C>
/// }
/// ```
///
/// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
/// - `normalize_impl_ty_args` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
/// - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
/// - `rebased_args` would be `[(A, B), u32, ^0.0]`, combining the args from
/// the *trait* with the generic associated type parameters (as bound vars).
///
/// A note regarding the use of bound vars here:
/// Imagine as an example
/// ```
/// trait Family {
/// type Member<C: Eq>;
/// }
///
/// impl Family for VecFamily {
/// type Member<C: Eq> = i32;
/// }
/// ```
/// Here, we would generate
/// ```ignore (pseudo-rust)
/// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) }
/// ```
///
/// when we really would like to generate
/// ```ignore (pseudo-rust)
/// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) }
/// ```
///
/// But, this is probably fine, because although the first clause can be used with types `C` that
/// do not implement `Eq`, for it to cause some kind of problem, there would have to be a
/// `VecFamily::Member<X>` for some type `X` where `!(X: Eq)`, that appears in the value of type
/// `Member<C: Eq> = ....` That type would fail a well-formedness check that we ought to be doing
/// elsewhere, which would check that any `<T as Family>::Member<X>` meets the bounds declared in
/// the trait (notably, that `X: Eq` and `T: Family`).
fn param_env_with_gat_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
impl_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> ty::ParamEnv<'tcx> {
let param_env = tcx.param_env(impl_ty.def_id);
let container_id = impl_ty.container_id(tcx);
let mut predicates = param_env.caller_bounds().to_vec();
// for RPITITs, we should install predicates that allow us to project all
// of the RPITITs associated with the same body. This is because checking
// the item bounds of RPITITs often involves nested RPITITs having to prove
// bounds about themselves.
let impl_tys_to_install = match impl_ty.opt_rpitit_info {
None => vec![impl_ty],
Some(
ty::ImplTraitInTraitData::Impl { fn_def_id }
| ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
) => tcx
.associated_types_for_impl_traits_in_associated_fn(fn_def_id)
.iter()
.map(|def_id| tcx.associated_item(*def_id))
.collect(),
};
for impl_ty in impl_tys_to_install {
let trait_ty = match impl_ty.container {
ty::AssocItemContainer::TraitContainer => impl_ty,
ty::AssocItemContainer::ImplContainer => {
tcx.associated_item(impl_ty.trait_item_def_id.unwrap())
}
};
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
// Extend the impl's identity args with late-bound GAT vars
let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id)
.extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
GenericParamDefKind::Type { .. } => {
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
Ty::new_bound(
tcx,
ty::INNERMOST,
ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
)
.into()
}
GenericParamDefKind::Lifetime => {
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Region(kind);
bound_vars.push(bound_var);
ty::Region::new_late_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind,
},
)
.into()
}
GenericParamDefKind::Const { .. } => {
let bound_var = ty::BoundVariableKind::Const;
bound_vars.push(bound_var);
ty::Const::new_bound(
tcx,
ty::INNERMOST,
ty::BoundVar::from_usize(bound_vars.len() - 1),
tcx.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
)
.into()
}
});
// When checking something like
//
// trait X { type Y: PartialEq<<Self as X>::Y> }
// impl X for T { default type Y = S; }
//
// We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case
// we want <T as X>::Y to normalize to S. This is valid because we are
// checking the default value specifically here. Add this equality to the
// ParamEnv for normalization specifically.
let normalize_impl_ty =
tcx.type_of(impl_ty.def_id).instantiate(tcx, normalize_impl_ty_args);
let rebased_args =
normalize_impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
match normalize_impl_ty.kind() {
ty::Alias(ty::Projection, proj)
if proj.def_id == trait_ty.def_id && proj.args == rebased_args =>
{
// Don't include this predicate if the projected type is
// exactly the same as the projection. This can occur in
// (somewhat dubious) code like this:
//
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
}
_ => predicates.push(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
projection_ty: ty::AliasTy::new(tcx, trait_ty.def_id, rebased_args),
term: normalize_impl_ty.into(),
},
bound_vars,
)
.to_predicate(tcx),
),
};
}
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
}
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
match impl_item.kind {
ty::AssocKind::Const => "const",

View file

@ -90,9 +90,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
use rustc_session::parse::feature_err;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol};
use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;

View file

@ -880,7 +880,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
(pair, r)
})
.unzip();
self.record_late_bound_vars(hir_id, binders.clone());
self.record_late_bound_vars(hir_id, binders);
// Even if there are no lifetimes defined here, we still wrap it in a binder
// scope. If there happens to be a nested poly trait ref (an error), that
// will be `Concatenating` anyways, so we don't have to worry about the depth

View file

@ -1,7 +1,7 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::source_map::Span;
use rustc_span::Span;
use std::ops::ControlFlow;
#[derive(Clone, PartialEq, Eq, Hash, Debug)]

View file

@ -14,8 +14,7 @@ use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::GenericArgs;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::sym;
use rustc_span::{sym, Span};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::ArgKind;

View file

@ -1,5 +1,4 @@
use rustc_span::source_map::DUMMY_SP;
use rustc_span::{self, Span};
use rustc_span::{self, Span, DUMMY_SP};
use std::{cmp, ops};
/// Tracks whether executing a node may exit normally (versus

View file

@ -52,8 +52,9 @@ use rustc_session::errors::ExprParenthesesNeeded;
use rustc_session::parse::feature_err;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{Span, Spanned};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use rustc_target::spec::abi::Abi::RustIntrinsic;
use rustc_trait_selection::infer::InferCtxtExt;

View file

@ -17,8 +17,9 @@ use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitableExt};
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{Span, Spanned};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use rustc_span::{BytePos, DUMMY_SP};
use rustc_target::abi::FieldIdx;
use rustc_trait_selection::traits::{ObligationCause, Pattern};

View file

@ -27,7 +27,7 @@ use rustc_index::IndexVec;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::GenericArg;
use rustc_middle::ty::{self, List, Ty, TyCtxt};
use rustc_span::source_map::Span;
use rustc_span::Span;
pub use rustc_middle::infer::canonical::*;
pub use substitute::CanonicalExt;

View file

@ -3,7 +3,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::lexical_region_resolve::RegionResolutionError::*;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::source_map::Span;
use rustc_span::Span;
mod different_lifetimes;
pub mod find_anon_type;

View file

@ -1,4 +1,6 @@
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use std::ops::ControlFlow;
@ -49,6 +51,12 @@ where
return ControlFlow::Continue(());
}
// FIXME: Don't consider alias bounds on types that have escaping bound
// vars. See #117455.
if ty.has_escaping_bound_vars() {
return ty.super_visit_with(self);
}
match ty.kind() {
// We can prove that an alias is live two ways:
// 1. All the components are live.

View file

@ -36,7 +36,6 @@ rustc_mir_transform = { path = "../rustc_mir_transform" }
rustc_monomorphize = { path = "../rustc_monomorphize" }
rustc_parse = { path = "../rustc_parse" }
rustc_passes = { path = "../rustc_passes" }
rustc_plugin_impl = { path = "../rustc_plugin_impl" }
rustc_privacy = { path = "../rustc_privacy" }
rustc_query_impl = { path = "../rustc_query_impl" }
rustc_query_system = { path = "../rustc_query_system" }

View file

@ -21,8 +21,9 @@ use rustc_session::config::{
use rustc_session::filesearch::sysroot_candidates;
use rustc_session::parse::ParseSess;
use rustc_session::{lint, CompilerIO, EarlyErrorHandler, Session};
use rustc_span::source_map::{FileLoader, FileName};
use rustc_span::source_map::FileLoader;
use rustc_span::symbol::sym;
use rustc_span::FileName;
use std::path::PathBuf;
use std::result;
use std::sync::Arc;
@ -353,7 +354,7 @@ pub struct Config {
pub hash_untracked_state: Option<Box<dyn FnOnce(&Session, &mut StableHasher) + Send>>,
/// This is a callback from the driver that is called when we're registering lints;
/// it is called during plugin registration when we have the LintStore in a non-shared state.
/// it is called during lint loading when we have the LintStore in a non-shared state.
///
/// Note that if you find a Some here you probably want to call that function in the new
/// function being registered.

View file

@ -23,11 +23,10 @@ use rustc_middle::util::Providers;
use rustc_mir_build as mir_build;
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
use rustc_passes::{self, abi_test, hir_stats, layout_test};
use rustc_plugin_impl as plugin;
use rustc_resolve::Resolver;
use rustc_session::code_stats::VTableSizeInfo;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::{MetadataLoader, Untracked};
use rustc_session::cstore::Untracked;
use rustc_session::output::filename_for_input;
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
@ -75,25 +74,12 @@ fn count_nodes(krate: &ast::Crate) -> usize {
pub(crate) fn create_lint_store(
sess: &Session,
metadata_loader: &dyn MetadataLoader,
register_lints: Option<impl Fn(&Session, &mut LintStore)>,
pre_configured_attrs: &[ast::Attribute],
) -> LintStore {
let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
if let Some(register_lints) = register_lints {
register_lints(sess, &mut lint_store);
}
let registrars = sess.time("plugin_loading", || {
plugin::load::load_plugins(sess, metadata_loader, pre_configured_attrs)
});
sess.time("plugin_registration", || {
let mut registry = plugin::Registry { lint_store: &mut lint_store };
for registrar in registrars {
registrar(&mut registry);
}
});
lint_store
}

View file

@ -148,12 +148,8 @@ impl<'tcx> Queries<'tcx> {
);
let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?;
let lint_store = Lrc::new(passes::create_lint_store(
sess,
&*self.codegen_backend().metadata_loader(),
self.compiler.register_lints.as_deref(),
&pre_configured_attrs,
));
let lint_store =
Lrc::new(passes::create_lint_store(sess, self.compiler.register_lints.as_deref()));
let cstore = FreezeLock::new(Box::new(CStore::new(
self.codegen_backend().metadata_loader(),
stable_crate_id,

View file

@ -817,7 +817,6 @@ fn test_unstable_options_tracking_hash() {
tracked!(split_lto_unit, Some(true));
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
tracked!(stack_protector, StackProtector::All);
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
tracked!(teach, true);
tracked!(thinlto, Some(true));
tracked!(thir_unsafeck, true);

View file

@ -109,7 +109,7 @@ struct LintAlias {
struct LintGroup {
lint_ids: Vec<LintId>,
from_plugin: bool,
is_loaded: bool,
depr: Option<LintAlias>,
}
@ -160,9 +160,7 @@ impl LintStore {
// Don't display deprecated lint groups.
depr.is_none()
})
.map(|(k, LintGroup { lint_ids, from_plugin, .. })| {
(*k, lint_ids.clone(), *from_plugin)
})
.map(|(k, LintGroup { lint_ids, is_loaded, .. })| (*k, lint_ids.clone(), *is_loaded))
}
pub fn register_early_pass(
@ -221,7 +219,7 @@ impl LintStore {
.entry(edition.lint_name())
.or_insert(LintGroup {
lint_ids: vec![],
from_plugin: lint.is_plugin,
is_loaded: lint.is_loaded,
depr: None,
})
.lint_ids
@ -234,7 +232,7 @@ impl LintStore {
.entry("future_incompatible")
.or_insert(LintGroup {
lint_ids: vec![],
from_plugin: lint.is_plugin,
is_loaded: lint.is_loaded,
depr: None,
})
.lint_ids
@ -249,7 +247,7 @@ impl LintStore {
alias,
LintGroup {
lint_ids: vec![],
from_plugin: false,
is_loaded: false,
depr: Some(LintAlias { name: lint_name, silent: true }),
},
);
@ -257,21 +255,21 @@ impl LintStore {
pub fn register_group(
&mut self,
from_plugin: bool,
is_loaded: bool,
name: &'static str,
deprecated_name: Option<&'static str>,
to: Vec<LintId>,
) {
let new = self
.lint_groups
.insert(name, LintGroup { lint_ids: to, from_plugin, depr: None })
.insert(name, LintGroup { lint_ids: to, is_loaded, depr: None })
.is_none();
if let Some(deprecated) = deprecated_name {
self.lint_groups.insert(
deprecated,
LintGroup {
lint_ids: vec![],
from_plugin,
is_loaded,
depr: Some(LintAlias { name, silent: false }),
},
);

View file

@ -10,7 +10,7 @@
//! all other analyses. The `LintPass`es built into rustc are defined
//! within [rustc_session::lint::builtin],
//! which has further comments on how to add such a lint.
//! rustc can also load user-defined lint plugins via the plugin mechanism.
//! rustc can also load external lint plugins, as is done for Clippy.
//!
//! Some of rustc's lints are defined elsewhere in the compiler and work by
//! calling `add_lint()` on the overall `Session` object. This works when

View file

@ -321,7 +321,7 @@ pub struct Lint {
pub future_incompatible: Option<FutureIncompatibleInfo>,
pub is_plugin: bool,
pub is_loaded: bool,
/// `Some` if this lint is feature gated, otherwise `None`.
pub feature_gate: Option<Symbol>,
@ -399,7 +399,7 @@ impl Lint {
default_level: Level::Forbid,
desc: "",
edition_lint_opts: None,
is_plugin: false,
is_loaded: false,
report_in_external_macro: false,
future_incompatible: None,
feature_gate: None,
@ -735,7 +735,7 @@ macro_rules! declare_lint {
name: stringify!($NAME),
default_level: $crate::$Level,
desc: $desc,
is_plugin: false,
is_loaded: false,
$($v: true,)*
$(feature_gate: Some($gate),)?
$(future_incompatible: Some($crate::FutureIncompatibleInfo {
@ -777,7 +777,7 @@ macro_rules! declare_tool_lint {
edition_lint_opts: None,
report_in_external_macro: $external,
future_incompatible: None,
is_plugin: true,
is_loaded: true,
$(feature_gate: Some($gate),)?
crate_level_only: false,
..$crate::Lint::default_fields_for_macro()

View file

@ -196,9 +196,6 @@ metadata_newer_crate_version =
metadata_no_crate_with_triple =
couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
metadata_no_dylib_plugin =
plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
metadata_no_link_mod_override =
overriding linking modifiers from command line is not supported

View file

@ -682,14 +682,6 @@ impl IntoDiagnostic<'_> for CannotFindCrate {
}
}
#[derive(Diagnostic)]
#[diag(metadata_no_dylib_plugin, code = "E0457")]
pub struct NoDylibPlugin {
#[primary_span]
pub span: Span,
pub crate_name: Symbol,
}
#[derive(Diagnostic)]
#[diag(metadata_crate_location_unknown_type)]
pub struct CrateLocationUnknownType<'a> {

View file

@ -220,7 +220,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::owned_slice::slice_owned;
use rustc_data_structures::svh::Svh;
use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_fs_util::try_canonicalize;
use rustc_session::config;
use rustc_session::cstore::{CrateSource, MetadataLoader};
@ -857,46 +857,6 @@ fn get_metadata_section<'p>(
}
}
/// Look for a plugin registrar. Returns its library path and crate disambiguator.
pub fn find_plugin_registrar(
sess: &Session,
metadata_loader: &dyn MetadataLoader,
span: Span,
name: Symbol,
) -> PathBuf {
find_plugin_registrar_impl(sess, metadata_loader, name).unwrap_or_else(|err| {
// `core` is always available if we got as far as loading plugins.
err.report(sess, span, false);
FatalError.raise()
})
}
fn find_plugin_registrar_impl<'a>(
sess: &'a Session,
metadata_loader: &dyn MetadataLoader,
name: Symbol,
) -> Result<PathBuf, CrateError> {
info!("find plugin registrar `{}`", name);
let mut locator = CrateLocator::new(
sess,
metadata_loader,
name,
false, // is_rlib
None, // hash
None, // extra_filename
true, // is_host
PathKind::Crate,
);
match locator.maybe_load_library_crate()? {
Some(library) => match library.source.dylib {
Some(dylib) => Ok(dylib.0),
None => Err(CrateError::NonDylibPlugin(name)),
},
None => Err(locator.into_error(None)),
}
}
/// A diagnostic function for dumping crate metadata to an output stream.
pub fn list_file_metadata(
target: &Target,
@ -964,7 +924,6 @@ pub(crate) enum CrateError {
DlOpen(String),
DlSym(String),
LocatorCombined(Box<CombinedLocatorError>),
NonDylibPlugin(Symbol),
NotFound(Symbol),
}
@ -1134,9 +1093,6 @@ impl CrateError {
});
}
}
CrateError::NonDylibPlugin(crate_name) => {
sess.emit_err(errors::NoDylibPlugin { span, crate_name });
}
CrateError::NotFound(crate_name) => {
sess.emit_err(errors::CannotFindCrate {
span,

View file

@ -69,6 +69,7 @@ macro_rules! arena_types {
[] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>,
[] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>,
[] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>,
[] canonical_goal_evaluation: rustc_middle::traits::solve::inspect::GoalEvaluationStep<'tcx>,
[] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>,
[] type_op_subtype:
rustc_middle::infer::canonical::Canonical<'tcx,

View file

@ -66,7 +66,7 @@ macro_rules! declare_hooks {
declare_hooks! {
/// Tries to destructure an `mir::Const` ADT or array into its variant index
/// and its field values. This should only be used for pretty printing.
hook try_destructure_mir_constant_for_diagnostics(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option<mir::DestructuredConstant<'tcx>>;
hook try_destructure_mir_constant_for_user_output(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option<mir::DestructuredConstant<'tcx>>;
/// Getting a &core::panic::Location referring to a span.
hook const_caller_location(file: rustc_span::Symbol, line: u32, col: u32) -> mir::ConstValue<'tcx>;

View file

@ -9,17 +9,15 @@ use rustc_session::lint::{
FutureIncompatibilityReason, Level, Lint, LintId,
};
use rustc_session::Session;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::{DesugaringKind, ExpnKind};
use rustc_span::{symbol, Span, Symbol, DUMMY_SP};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::{symbol, DesugaringKind, Span, Symbol, DUMMY_SP};
use crate::ty::TyCtxt;
/// How a lint level was set.
#[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)]
pub enum LintLevelSource {
/// Lint is at the default level as declared
/// in rustc or a plugin.
/// Lint is at the default level as declared in rustc.
Default,
/// Lint level was set by an attribute.

View file

@ -10,8 +10,8 @@ use rustc_hir::ItemId;
use rustc_index::Idx;
use rustc_query_system::ich::StableHashingContext;
use rustc_session::config::OptLevel;
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use std::fmt;
use std::hash::Hash;

View file

@ -1713,7 +1713,7 @@ fn pretty_print_const_value_tcx<'tcx>(
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
let ct = tcx.lift(ct).unwrap();
let ty = tcx.lift(ty).unwrap();
if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics(ct, ty) {
if let Some(contents) = tcx.try_destructure_mir_constant_for_user_output(ct, ty) {
let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec();
match *ty.kind() {
ty::Array(..) => {

View file

@ -10,7 +10,7 @@ use crate::infer::canonical::{Canonical, QueryResponse};
use crate::ty::error::TypeError;
use crate::ty::GenericArg;
use crate::ty::{self, Ty, TyCtxt};
use rustc_span::source_map::Span;
use rustc_span::Span;
pub mod type_op {
use crate::ty::fold::TypeFoldable;

View file

@ -1,4 +1,4 @@
use super::{CanonicalInput, QueryResult};
use super::{inspect, CanonicalInput, QueryResult};
use crate::ty::TyCtxt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lock;
@ -14,8 +14,10 @@ pub struct EvaluationCache<'tcx> {
map: Lock<FxHashMap<CanonicalInput<'tcx>, CacheEntry<'tcx>>>,
}
#[derive(PartialEq, Eq)]
pub struct CacheData<'tcx> {
pub result: QueryResult<'tcx>,
pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>,
pub reached_depth: usize,
pub encountered_overflow: bool,
}
@ -24,22 +26,33 @@ impl<'tcx> EvaluationCache<'tcx> {
/// Insert a final result into the global cache.
pub fn insert(
&self,
tcx: TyCtxt<'tcx>,
key: CanonicalInput<'tcx>,
proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>,
reached_depth: usize,
did_overflow: bool,
encountered_overflow: bool,
cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
dep_node: DepNodeIndex,
result: QueryResult<'tcx>,
) {
let mut map = self.map.borrow_mut();
let entry = map.entry(key).or_default();
let data = WithDepNode::new(dep_node, result);
let data = WithDepNode::new(dep_node, QueryData { result, proof_tree });
entry.cycle_participants.extend(cycle_participants);
if did_overflow {
if encountered_overflow {
entry.with_overflow.insert(reached_depth, data);
} else {
entry.success = Some(Success { data, reached_depth });
}
if cfg!(debug_assertions) {
drop(map);
if Some(CacheData { result, proof_tree, reached_depth, encountered_overflow })
!= self.get(tcx, key, |_| false, Limit(reached_depth))
{
bug!("unable to retrieve inserted element from cache: {key:?}");
}
}
}
/// Try to fetch a cached result, checking the recursion limit
@ -62,27 +75,39 @@ impl<'tcx> EvaluationCache<'tcx> {
if let Some(ref success) = entry.success {
if available_depth.value_within_limit(success.reached_depth) {
let QueryData { result, proof_tree } = success.data.get(tcx);
return Some(CacheData {
result: success.data.get(tcx),
result,
proof_tree,
reached_depth: success.reached_depth,
encountered_overflow: false,
});
}
}
entry.with_overflow.get(&available_depth.0).map(|e| CacheData {
result: e.get(tcx),
reached_depth: available_depth.0,
encountered_overflow: true,
entry.with_overflow.get(&available_depth.0).map(|e| {
let QueryData { result, proof_tree } = e.get(tcx);
CacheData {
result,
proof_tree,
reached_depth: available_depth.0,
encountered_overflow: true,
}
})
}
}
struct Success<'tcx> {
data: WithDepNode<QueryResult<'tcx>>,
data: WithDepNode<QueryData<'tcx>>,
reached_depth: usize,
}
#[derive(Clone, Copy)]
pub struct QueryData<'tcx> {
pub result: QueryResult<'tcx>,
pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]>,
}
/// The cache entry for a goal `CanonicalInput`.
///
/// This contains results whose computation never hit the
@ -96,5 +121,5 @@ struct CacheEntry<'tcx> {
/// See the doc comment of `StackEntry::cycle_participants` for more
/// details.
cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
with_overflow: FxHashMap<usize, WithDepNode<QueryResult<'tcx>>>,
with_overflow: FxHashMap<usize, WithDepNode<QueryData<'tcx>>>,
}

View file

@ -42,12 +42,6 @@ pub struct State<'tcx, T> {
pub type CanonicalState<'tcx, T> = Canonical<'tcx, State<'tcx, T>>;
#[derive(Debug, Eq, PartialEq)]
pub enum CacheHit {
Provisional,
Global,
}
/// When evaluating the root goals we also store the
/// original values for the `CanonicalVarValues` of the
/// canonicalized goal. We use this to map any [CanonicalState]
@ -78,8 +72,8 @@ pub struct CanonicalGoalEvaluation<'tcx> {
#[derive(Eq, PartialEq)]
pub enum CanonicalGoalEvaluationKind<'tcx> {
Overflow,
CacheHit(CacheHit),
Uncached { revisions: Vec<GoalEvaluationStep<'tcx>> },
CycleInStack,
Evaluation { revisions: &'tcx [GoalEvaluationStep<'tcx>] },
}
impl Debug for GoalEvaluation<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

View file

@ -74,13 +74,10 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
CanonicalGoalEvaluationKind::Overflow => {
writeln!(self.f, "OVERFLOW: {:?}", eval.result)
}
CanonicalGoalEvaluationKind::CacheHit(CacheHit::Global) => {
writeln!(self.f, "GLOBAL CACHE HIT: {:?}", eval.result)
CanonicalGoalEvaluationKind::CycleInStack => {
writeln!(self.f, "CYCLE IN STACK: {:?}", eval.result)
}
CanonicalGoalEvaluationKind::CacheHit(CacheHit::Provisional) => {
writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", eval.result)
}
CanonicalGoalEvaluationKind::Uncached { revisions } => {
CanonicalGoalEvaluationKind::Evaluation { revisions } => {
for (n, step) in revisions.iter().enumerate() {
writeln!(self.f, "REVISION {n}")?;
self.nested(|this| this.format_evaluation_step(step))?;

View file

@ -1107,8 +1107,10 @@ impl<'tcx> Ty<'tcx> {
// This doesn't depend on regions, so try to minimize distinct
// query keys used.
// If normalization fails, we just use `query_ty`.
let query_ty =
tcx.try_normalize_erasing_regions(param_env, query_ty).unwrap_or(query_ty);
debug_assert!(!param_env.has_infer());
let query_ty = tcx
.try_normalize_erasing_regions(param_env, query_ty)
.unwrap_or_else(|_| tcx.erase_regions(query_ty));
tcx.needs_drop_raw(param_env.and(query_ty))
}
@ -1297,7 +1299,6 @@ pub fn needs_drop_components<'tcx>(
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::Char
| ty::CoroutineWitness(..)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::Str => Ok(SmallVec::new()),
@ -1337,7 +1338,8 @@ pub fn needs_drop_components<'tcx>(
| ty::Placeholder(..)
| ty::Infer(_)
| ty::Closure(..)
| ty::Coroutine(..) => Ok(smallvec![ty]),
| ty::Coroutine(..)
| ty::CoroutineWitness(..) => Ok(smallvec![ty]),
}
}

View file

@ -856,7 +856,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
PatKind::InlineConstant { ref subpattern, .. } => {
self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f)
self.visit_primary_bindings(subpattern, pattern_user_ty, f)
}
PatKind::Leaf { ref subpatterns } => {

View file

@ -186,8 +186,9 @@ use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyC
use rustc_session::config::EntryFnType;
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
use rustc_session::Limit;
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
use rustc_span::source_map::{dummy_spanned, respan, Spanned};
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::Size;
use std::path::PathBuf;

View file

@ -526,6 +526,9 @@ parse_missing_fn_for_function_definition = missing `fn` for function definition
parse_missing_fn_for_method_definition = missing `fn` for method definition
.suggestion = add `fn` here to parse `{$ident}` as a public method
parse_missing_fn_params = missing parameters for function definition
.suggestion = add a parameter list
parse_missing_for_in_trait_impl = missing `for` in a trait impl
.suggestion = add `for` here

View file

@ -1551,6 +1551,14 @@ pub(crate) enum AmbiguousMissingKwForItemSub {
HelpMacro,
}
#[derive(Diagnostic)]
#[diag(parse_missing_fn_params)]
pub(crate) struct MissingFnParams {
#[primary_span]
#[suggestion(code = "()", applicability = "machine-applicable", style = "short")]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_missing_trait_in_trait_impl)]
pub(crate) struct MissingTraitInTraitImpl {

View file

@ -32,10 +32,10 @@ use rustc_macros::Subdiagnostic;
use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_span::source_map::{self, Span, Spanned};
use rustc_span::source_map::{self, Spanned};
use rustc_span::symbol::kw::PathRoot;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Pos};
use rustc_span::{BytePos, Pos, Span};
use thin_vec::{thin_vec, ThinVec};
/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression

View file

@ -22,9 +22,9 @@ use rustc_errors::{
};
use rustc_span::edit_distance::edit_distance;
use rustc_span::edition::Edition;
use rustc_span::source_map::{self, Span};
use rustc_span::source_map;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::DUMMY_SP;
use rustc_span::{Span, DUMMY_SP};
use std::fmt::Write;
use std::mem;
use thin_vec::{thin_vec, ThinVec};
@ -2499,6 +2499,16 @@ impl<'a> Parser<'a> {
pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, ThinVec<Param>> {
let mut first_param = true;
// Parse the arguments, starting out with `self` being allowed...
if self.token.kind != TokenKind::OpenDelim(Delimiter::Parenthesis)
// might be typo'd trait impl, handled elsewhere
&& !self.token.is_keyword(kw::For)
{
// recover from missing argument list, e.g. `fn main -> () {}`
self.sess
.emit_err(errors::MissingFnParams { span: self.prev_token.span.shrink_to_hi() });
return Ok(ThinVec::new());
}
let (mut params, _) = self.parse_paren_comma_seq(|p| {
p.recover_diff_marker();
let snapshot = p.create_snapshot_for_diagnostic();

View file

@ -36,8 +36,8 @@ use rustc_errors::{
Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan,
};
use rustc_session::parse::ParseSess;
use rustc_span::source_map::{Span, DUMMY_SP};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use std::ops::Range;
use std::{mem, slice};
use thin_vec::ThinVec;

View file

@ -20,8 +20,9 @@ use rustc_ast::{
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::{respan, Span, Spanned};
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
#[derive(PartialEq, Copy, Clone)]

View file

@ -10,8 +10,8 @@ use rustc_ast::{
Path, PathSegment, QSelf,
};
use rustc_errors::{Applicability, IntoDiagnostic, PResult};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span};
use std::mem;
use thin_vec::ThinVec;
use tracing::debug;

View file

@ -20,8 +20,8 @@ use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyl
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Stmt};
use rustc_ast::{StmtKind, DUMMY_NODE_ID};
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span};
use std::borrow::Cow;
use std::mem;

View file

@ -18,9 +18,8 @@ use rustc_ast::{
TraitObjectSyntax, Ty, TyKind,
};
use rustc_errors::{Applicability, PResult};
use rustc_span::source_map::Span;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Symbol;
use rustc_span::{Span, Symbol};
use thin_vec::{thin_vec, ThinVec};
/// Any `?`, `!`, or `~const` modifiers that appear at the start of a bound.

View file

@ -589,9 +589,6 @@ passes_pass_by_value =
`pass_by_value` attribute should be applied to a struct, enum or type alias
.label = is not a struct, enum or type alias
passes_plugin_registrar =
`#[plugin_registrar]` only has an effect on functions
passes_proc_macro_bad_sig = {$kind} has incorrect signature
passes_repr_conflicting =

View file

@ -211,7 +211,6 @@ impl CheckAttrVisitor<'_> {
sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
sym::macro_export => self.check_macro_export(hir_id, attr, target),
sym::ignore | sym::should_panic => {
self.check_generic_attr(hir_id, attr, target, Target::Fn)
@ -2237,17 +2236,6 @@ impl CheckAttrVisitor<'_> {
}
}
fn check_plugin_registrar(&self, hir_id: HirId, attr: &Attribute, target: Target) {
if target != Target::Fn {
self.tcx.emit_spanned_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::PluginRegistrar,
);
}
}
fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
// Warn on useless empty attributes.
let note = if matches!(

View file

@ -717,10 +717,6 @@ pub enum MacroExport {
TooManyItems,
}
#[derive(LintDiagnostic)]
#[diag(passes_plugin_registrar)]
pub struct PluginRegistrar;
#[derive(Subdiagnostic)]
pub enum UnusedNote {
#[note(passes_unused_empty_lints_note)]

View file

@ -1,18 +0,0 @@
[package]
name = "rustc_plugin_impl"
version = "0.0.0"
build = false
edition = "2021"
[dependencies]
# tidy-alphabetical-start
libloading = "0.7.1"
rustc_ast = { path = "../rustc_ast" }
rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_lint = { path = "../rustc_lint" }
rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
# tidy-alphabetical-end

View file

@ -1,4 +0,0 @@
plugin_impl_load_plugin_error = {$msg}
plugin_impl_malformed_plugin_attribute = malformed `plugin` attribute
.label = malformed attribute

View file

@ -1,20 +0,0 @@
//! Errors emitted by plugin_impl
use rustc_macros::Diagnostic;
use rustc_span::Span;
#[derive(Diagnostic)]
#[diag(plugin_impl_load_plugin_error)]
pub struct LoadPluginError {
#[primary_span]
pub span: Span,
pub msg: String,
}
#[derive(Diagnostic)]
#[diag(plugin_impl_malformed_plugin_attribute, code = "E0498")]
pub struct MalformedPluginAttribute {
#[primary_span]
#[label]
pub span: Span,
}

View file

@ -1,33 +0,0 @@
//! Infrastructure for compiler plugins.
//!
//! Plugins are a deprecated way to extend the behavior of `rustc` in various ways.
//!
//! See the [`plugin`
//! feature](https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html)
//! of the Unstable Book for some examples.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![cfg_attr(not(bootstrap), doc(rust_logo))]
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![cfg_attr(not(bootstrap), allow(internal_features))]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_fluent_macro::fluent_messages;
use rustc_lint::LintStore;
mod errors;
pub mod load;
fluent_messages! { "../messages.ftl" }
/// Structure used to register plugins.
///
/// A plugin registrar function takes an `&mut Registry` and should call
/// methods to register its plugins.
pub struct Registry<'a> {
/// The `LintStore` allows plugins to register new lints.
pub lint_store: &'a mut LintStore,
}

View file

@ -1,78 +0,0 @@
//! Used by `rustc` when loading a plugin.
use crate::errors::{LoadPluginError, MalformedPluginAttribute};
use crate::Registry;
use libloading::Library;
use rustc_ast::Attribute;
use rustc_metadata::locator;
use rustc_session::cstore::MetadataLoader;
use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
use std::env;
use std::mem;
use std::path::PathBuf;
/// Pointer to a registrar function.
type PluginRegistrarFn = fn(&mut Registry<'_>);
/// Read plugin metadata and dynamically load registrar functions.
pub fn load_plugins(
sess: &Session,
metadata_loader: &dyn MetadataLoader,
attrs: &[Attribute],
) -> Vec<PluginRegistrarFn> {
let mut plugins = Vec::new();
for attr in attrs {
if !attr.has_name(sym::plugin) {
continue;
}
for plugin in attr.meta_item_list().unwrap_or_default() {
match plugin.ident() {
Some(ident) if plugin.is_word() => {
load_plugin(&mut plugins, sess, metadata_loader, ident)
}
_ => {
sess.emit_err(MalformedPluginAttribute { span: plugin.span() });
}
}
}
}
plugins
}
fn load_plugin(
plugins: &mut Vec<PluginRegistrarFn>,
sess: &Session,
metadata_loader: &dyn MetadataLoader,
ident: Ident,
) {
let lib = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name);
let fun = dylink_registrar(lib).unwrap_or_else(|err| {
// This is fatal: there are almost certainly macros we need inside this crate, so
// continuing would spew "macro undefined" errors.
sess.emit_fatal(LoadPluginError { span: ident.span, msg: err.to_string() });
});
plugins.push(fun);
}
/// Dynamically link a registrar function into the compiler process.
fn dylink_registrar(lib_path: PathBuf) -> Result<PluginRegistrarFn, libloading::Error> {
// Make sure the path contains a / or the linker will search for it.
let lib_path = env::current_dir().unwrap().join(&lib_path);
let lib = unsafe { Library::new(&lib_path) }?;
let registrar_sym = unsafe { lib.get::<PluginRegistrarFn>(b"__rustc_plugin_registrar") }?;
// Intentionally leak the dynamic library. We can't ever unload it
// since the library can make things that will live arbitrarily long
// (e.g., an Rc cycle or a thread).
let registrar_sym = unsafe { registrar_sym.into_raw() };
mem::forget(lib);
Ok(*registrar_sym)
}

View file

@ -18,10 +18,9 @@ use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
use rustc_feature::UnstableFeatures;
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
use rustc_span::source_map::{FileName, FilePathMapping};
use rustc_span::source_map::FilePathMapping;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::SourceFileHashAlgorithm;
use rustc_span::{FileNameDisplayPreference, RealFileName};
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm};
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
@ -2674,28 +2673,19 @@ pub fn build_session_options(
);
}
// Handle both `-Z symbol-mangling-version` and `-C symbol-mangling-version`; the latter takes
// precedence.
match (cg.symbol_mangling_version, unstable_opts.symbol_mangling_version) {
(Some(smv_c), Some(smv_z)) if smv_c != smv_z => {
handler.early_error(
"incompatible values passed for `-C symbol-mangling-version` \
and `-Z symbol-mangling-version`",
);
// Check for unstable values of `-C symbol-mangling-version`.
// This is what prevents them from being used on stable compilers.
match cg.symbol_mangling_version {
// Stable values:
None | Some(SymbolManglingVersion::V0) => {}
// Unstable values:
Some(SymbolManglingVersion::Legacy) => {
if !unstable_opts.unstable_options {
handler.early_error(
"`-C symbol-mangling-version=legacy` requires `-Z unstable-options`",
);
}
}
(Some(SymbolManglingVersion::V0), _) => {}
(Some(_), _) if !unstable_opts.unstable_options => {
handler
.early_error("`-C symbol-mangling-version=legacy` requires `-Z unstable-options`");
}
(None, None) => {}
(None, smv) => {
handler.early_warn(
"`-Z symbol-mangling-version` is deprecated; use `-C symbol-mangling-version`",
);
cg.symbol_mangling_version = smv;
}
_ => {}
}
// Check for unstable values of `-C instrument-coverage`.

View file

@ -1529,8 +1529,6 @@ options! {
dump_solver_proof_tree: DumpSolverProofTree = (DumpSolverProofTree::Never, parse_dump_solver_proof_tree, [UNTRACKED],
"dump a proof tree for every goal evaluated by the new trait solver. If the flag is specified without any options after it
then it defaults to `always`. If the flag is not specified at all it defaults to `on-request`."),
dump_solver_proof_tree_use_cache: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
"determines whether dumped proof trees use the global cache"),
dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
dylib_lto: bool = (false, parse_bool, [UNTRACKED],
@ -1823,9 +1821,6 @@ written to standard error output)"),
"control if mem::uninitialized and mem::zeroed panic on more UB"),
strip: Strip = (Strip::None, parse_strip, [UNTRACKED],
"tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
symbol_mangling_version: Option<SymbolManglingVersion> = (None,
parse_symbol_mangling_version, [TRACKED],
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
#[rustc_lint_opt_deny_field_access("use `Session::teach` instead of this field")]
teach: bool = (false, parse_bool, [TRACKED],
"show extended diagnostic help (default: no)"),

View file

@ -31,8 +31,8 @@ use rustc_errors::{
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
use rustc_span::edition::Edition;
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap, Span};
use rustc_span::{SourceFileHashAlgorithm, Symbol};
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap};
use rustc_span::{SourceFileHashAlgorithm, Span, Symbol};
use rustc_target::asm::InlineAsmArch;
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
use rustc_target::spec::{

View file

@ -1,13 +1,11 @@
/// Used as a return value to signify a fatal error occurred. (It is also
/// used as the argument to panic at the moment, but that will eventually
/// not be true.)
/// Used as a return value to signify a fatal error occurred.
#[derive(Copy, Clone, Debug)]
#[must_use]
pub struct FatalError;
pub struct FatalErrorMarker;
// Don't implement Send on FatalError. This makes it impossible to panic!(FatalError).
// Don't implement Send on FatalError. This makes it impossible to `panic_any!(FatalError)`.
// We don't want to invoke the panic handler and print a backtrace for fatal errors.
impl !Send for FatalError {}

View file

@ -24,16 +24,13 @@
// because getting it wrong can lead to nested `HygieneData::with` calls that
// trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
use crate::edition::Edition;
use crate::symbol::{kw, sym, Symbol};
use crate::with_session_globals;
use crate::{HashStableContext, Span, DUMMY_SP};
use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
use crate::{with_session_globals, HashStableContext, Span, DUMMY_SP};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stable_hasher::HashingControls;
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_data_structures::stable_hasher::{Hash64, HashStable, HashingControls, StableHasher};
use rustc_data_structures::sync::{Lock, Lrc, WorkerLocal};
use rustc_data_structures::unhash::UnhashMap;
use rustc_index::IndexVec;
@ -130,7 +127,7 @@ impl ExpnHash {
/// Returns the crate-local part of the [ExpnHash].
///
/// Used for tests.
/// Used for assertions.
#[inline]
pub fn local_hash(self) -> Hash64 {
self.0.split().1
@ -173,7 +170,7 @@ impl LocalExpnId {
pub const ROOT: LocalExpnId = LocalExpnId::from_u32(0);
#[inline]
pub fn from_raw(idx: ExpnIndex) -> LocalExpnId {
fn from_raw(idx: ExpnIndex) -> LocalExpnId {
LocalExpnId::from_u32(idx.as_u32())
}
@ -204,11 +201,6 @@ impl LocalExpnId {
})
}
#[inline]
pub fn expn_hash(self) -> ExpnHash {
HygieneData::with(|data| data.local_expn_hash(self))
}
#[inline]
pub fn expn_data(self) -> ExpnData {
HygieneData::with(|data| data.local_expn_data(self).clone())
@ -239,13 +231,6 @@ impl LocalExpnId {
self.to_expn_id().is_descendant_of(ancestor.to_expn_id())
}
/// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
/// `expn_id.is_descendant_of(ctxt.outer_expn())`.
#[inline]
pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
self.to_expn_id().outer_expn_is_descendant_of(ctxt)
}
/// Returns span for the macro which originally caused this expansion to happen.
///
/// Stops backtracing at include! boundary.
@ -253,12 +238,6 @@ impl LocalExpnId {
pub fn expansion_cause(self) -> Option<Span> {
self.to_expn_id().expansion_cause()
}
#[inline]
#[track_caller]
pub fn parent(self) -> LocalExpnId {
self.expn_data().parent.as_local().unwrap()
}
}
impl ExpnId {
@ -333,7 +312,7 @@ impl ExpnId {
}
#[derive(Debug)]
pub struct HygieneData {
pub(crate) struct HygieneData {
/// Each expansion should have an associated expansion data, but sometimes there's a delay
/// between creation of an expansion ID and obtaining its data (e.g. macros are collected
/// first and then resolved later), so we use an `Option` here.
@ -384,15 +363,10 @@ impl HygieneData {
}
}
pub fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow_mut()))
}
#[inline]
fn local_expn_hash(&self, expn_id: LocalExpnId) -> ExpnHash {
self.local_expn_hashes[expn_id]
}
#[inline]
fn expn_hash(&self, expn_id: ExpnId) -> ExpnHash {
match expn_id.as_local() {
@ -746,7 +720,7 @@ impl SyntaxContext {
}
/// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0.
pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
pub(crate) fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
HygieneData::with(|data| {
*self = data.normalize_to_macros_2_0(*self);
data.adjust(self, expn_id)
@ -779,7 +753,11 @@ impl SyntaxContext {
/// ```
/// This returns `None` if the context cannot be glob-adjusted.
/// Otherwise, it returns the scope to use when privacy checking (see `adjust` for details).
pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
pub(crate) fn glob_adjust(
&mut self,
expn_id: ExpnId,
glob_span: Span,
) -> Option<Option<ExpnId>> {
HygieneData::with(|data| {
let mut scope = None;
let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
@ -803,7 +781,7 @@ impl SyntaxContext {
/// assert!(self.glob_adjust(expansion, glob_ctxt) == Some(privacy_checking_scope));
/// }
/// ```
pub fn reverse_glob_adjust(
pub(crate) fn reverse_glob_adjust(
&mut self,
expn_id: ExpnId,
glob_span: Span,
@ -858,11 +836,11 @@ impl SyntaxContext {
}
#[inline]
pub fn outer_mark(self) -> (ExpnId, Transparency) {
fn outer_mark(self) -> (ExpnId, Transparency) {
HygieneData::with(|data| data.outer_mark(self))
}
pub fn dollar_crate_name(self) -> Symbol {
pub(crate) fn dollar_crate_name(self) -> Symbol {
HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
}
@ -961,12 +939,12 @@ pub struct ExpnData {
/// The normal module (`mod`) in which the expanded macro was defined.
pub parent_module: Option<DefId>,
/// Suppresses the `unsafe_code` lint for code produced by this macro.
pub allow_internal_unsafe: bool,
pub(crate) allow_internal_unsafe: bool,
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
pub local_inner_macros: bool,
/// Should debuginfo for the macro be collapsed to the outermost expansion site (in other
/// words, was the macro definition annotated with `#[collapse_debuginfo]`)?
pub collapse_debuginfo: bool,
pub(crate) collapse_debuginfo: bool,
}
impl !PartialEq for ExpnData {}

View file

@ -4,10 +4,12 @@
//!
//! - the *span*, represented by [`SpanData`] and related types;
//! - source code as represented by a [`SourceMap`]; and
//! - interned strings, represented by [`Symbol`]s, with some common symbols available statically in the [`sym`] module.
//! - interned strings, represented by [`Symbol`]s, with some common symbols available statically
//! in the [`sym`] module.
//!
//! Unlike most compilers, the span contains not only the position in the source code, but also various other metadata,
//! such as the edition and macro hygiene. This metadata is stored in [`SyntaxContext`] and [`ExpnData`].
//! Unlike most compilers, the span contains not only the position in the source code, but also
//! various other metadata, such as the edition and macro hygiene. This metadata is stored in
//! [`SyntaxContext`] and [`ExpnData`].
//!
//! ## Note
//!
@ -117,7 +119,6 @@ impl SessionGlobals {
}
}
#[inline]
pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
assert!(
!SESSION_GLOBALS.is_set(),
@ -128,7 +129,6 @@ pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -
SESSION_GLOBALS.set(&session_globals, f)
}
#[inline]
pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnOnce() -> R) -> R {
assert!(
!SESSION_GLOBALS.is_set(),
@ -138,7 +138,6 @@ pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnO
SESSION_GLOBALS.set(session_globals, f)
}
#[inline]
pub fn create_default_session_if_not_set_then<R, F>(f: F) -> R
where
F: FnOnce(&SessionGlobals) -> R,
@ -146,7 +145,6 @@ where
create_session_if_not_set_then(edition::DEFAULT_EDITION, f)
}
#[inline]
pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
where
F: FnOnce(&SessionGlobals) -> R,
@ -159,7 +157,6 @@ where
}
}
#[inline]
pub fn with_session_globals<R, F>(f: F) -> R
where
F: FnOnce(&SessionGlobals) -> R,
@ -167,7 +164,6 @@ where
SESSION_GLOBALS.with(f)
}
#[inline]
pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
create_session_globals_then(edition::DEFAULT_EDITION, f)
}
@ -179,8 +175,7 @@ scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);
// FIXME: We should use this enum or something like it to get rid of the
// use of magic `/rust/1.x/...` paths across the board.
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd)]
#[derive(Decodable)]
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable)]
pub enum RealFileName {
LocalPath(PathBuf),
/// For remapped paths (namely paths into libstd that have been mapped
@ -217,8 +212,8 @@ impl<S: Encoder> Encodable<S> for RealFileName {
RealFileName::Remapped { ref local_path, ref virtual_name } => encoder
.emit_enum_variant(1, |encoder| {
// For privacy and build reproducibility, we must not embed host-dependant path in artifacts
// if they have been remapped by --remap-path-prefix
// For privacy and build reproducibility, we must not embed host-dependant path
// in artifacts if they have been remapped by --remap-path-prefix
assert!(local_path.is_none());
local_path.encode(encoder);
virtual_name.encode(encoder);
@ -954,7 +949,7 @@ impl Span {
/// Produces a span with the same location as `self` and context produced by a macro with the
/// given ID and transparency, assuming that macro was defined directly and not produced by
/// some other macro (which is the case for built-in and procedural macros).
pub fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
self.with_ctxt(SyntaxContext::root().apply_mark(expn_id, transparency))
}
@ -1529,7 +1524,8 @@ impl SourceFile {
})
}
/// This converts the `lines` field to contain `SourceFileLines::Lines` if needed and freezes it.
/// This converts the `lines` field to contain `SourceFileLines::Lines` if needed and freezes
/// it.
fn convert_diffs_to_lines_frozen(&self) {
let mut guard = if let Some(guard) = self.lines.try_write() { guard } else { return };
@ -2247,6 +2243,9 @@ where
/// Useful type to use with `Result<>` indicate that an error has already
/// been reported to the user, so no need to continue checking.
///
/// The `()` field is necessary: it is non-`pub`, which means values of this
/// type cannot be constructed outside of this crate.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(HashStable_Generic)]
pub struct ErrorGuaranteed(());
@ -2264,7 +2263,8 @@ impl<E: rustc_serialize::Encoder> Encodable<E> for ErrorGuaranteed {
#[inline]
fn encode(&self, _e: &mut E) {
panic!(
"should never serialize an `ErrorGuaranteed`, as we do not write metadata or incremental caches in case errors occurred"
"should never serialize an `ErrorGuaranteed`, as we do not write metadata or \
incremental caches in case errors occurred"
)
}
}

View file

@ -9,20 +9,15 @@
//! within the `SourceMap`, which upon request can be converted to line and column
//! information, source code snippets, etc.
pub use crate::hygiene::{ExpnData, ExpnKind};
pub use crate::*;
use crate::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{Hash128, Hash64, StableHasher};
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc, MappedReadGuard, ReadGuard, RwLock};
use std::cmp;
use std::hash::Hash;
use std::path::{self, Path, PathBuf};
use std::fs;
use std::io;
use std::io::BorrowedBuf;
use std::io::Read;
use std::hash::Hash;
use std::io::{self, BorrowedBuf, Read};
use std::path::{self, Path, PathBuf};
#[cfg(test)]
mod tests;
@ -41,7 +36,7 @@ pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
}
}
pub mod monotonic {
mod monotonic {
use std::ops::{Deref, DerefMut};
/// A `MonotonicVec` is a `Vec` which can only be grown.
@ -51,18 +46,14 @@ pub mod monotonic {
// field is inaccessible
pub struct MonotonicVec<T>(Vec<T>);
impl<T> MonotonicVec<T> {
pub fn new(val: Vec<T>) -> MonotonicVec<T> {
MonotonicVec(val)
}
pub fn push(&mut self, val: T) {
pub(super) fn push(&mut self, val: T) {
self.0.push(val);
}
}
impl<T> Default for MonotonicVec<T> {
fn default() -> Self {
MonotonicVec::new(vec![])
MonotonicVec(vec![])
}
}
@ -207,7 +198,7 @@ impl StableSourceFileId {
//
#[derive(Default)]
pub(super) struct SourceMapFiles {
struct SourceMapFiles {
source_files: monotonic::MonotonicVec<Lrc<SourceFile>>,
stable_id_to_source_file: FxHashMap<StableSourceFileId, Lrc<SourceFile>>,
}
@ -466,33 +457,6 @@ impl SourceMap {
self.span_to_string(sp, FileNameDisplayPreference::Remapped)
}
/// Format the span location suitable for pretty printing annotations with relative line numbers
pub fn span_to_relative_line_string(&self, sp: Span, relative_to: Span) -> String {
if self.files.borrow().source_files.is_empty() || sp.is_dummy() || relative_to.is_dummy() {
return "no-location".to_string();
}
let lo = self.lookup_char_pos(sp.lo());
let hi = self.lookup_char_pos(sp.hi());
let offset = self.lookup_char_pos(relative_to.lo());
if lo.file.name != offset.file.name || !relative_to.contains(sp) {
return self.span_to_embeddable_string(sp);
}
let lo_line = lo.line.saturating_sub(offset.line);
let hi_line = hi.line.saturating_sub(offset.line);
format!(
"{}:+{}:{}: +{}:{}",
lo.file.name.display(FileNameDisplayPreference::Remapped),
lo_line,
lo.col.to_usize() + 1,
hi_line,
hi.col.to_usize() + 1,
)
}
/// Format the span location to be printed in diagnostics. Must not be emitted
/// to build artifacts as this may leak local file paths. Use span_to_embeddable_string
/// for string suitable for embedding.

View file

@ -3,7 +3,7 @@
//! type, and vice versa.
use rustc_arena::DroplessArena;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
use rustc_data_structures::sync::Lock;
use rustc_macros::HashStable_Generic;
@ -20,8 +20,8 @@ mod tests;
// The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
symbols! {
// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order.
// If you modify this list, adjust `is_special` and `is_used_keyword`/`is_unused_keyword`.
// But this should rarely be necessary if the keywords are kept in alphabetic order.
Keywords {
// Special reserved identifiers used internally for elided lifetimes,
// unnamed method parameters, crate root module, error recovery etc.
@ -316,6 +316,7 @@ symbols! {
ToOwned,
ToString,
TokenStream,
Trait,
Try,
TryCaptureGeneric,
TryCapturePrintable,
@ -893,7 +894,7 @@ symbols! {
inline_const_pat,
inout,
instruction_set,
integer_: "integer",
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
integral,
into_future,
into_iter,
@ -2076,43 +2077,33 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
}
}
#[derive(Default)]
pub(crate) struct Interner(Lock<InternerInner>);
// The `&'static str`s in this type actually point into the arena.
//
// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
// found that to regress performance up to 2% in some cases. This might be
// revisited after further improvements to `indexmap`.
//
// This type is private to prevent accidentally constructing more than one
// `Interner` on the same thread, which makes it easy to mix up `Symbol`s
// between `Interner`s.
#[derive(Default)]
struct InternerInner {
arena: DroplessArena,
names: FxHashMap<&'static str, Symbol>,
strings: Vec<&'static str>,
strings: FxIndexSet<&'static str>,
}
impl Interner {
fn prefill(init: &[&'static str]) -> Self {
Interner(Lock::new(InternerInner {
strings: init.into(),
names: init.iter().copied().zip((0..).map(Symbol::new)).collect(),
..Default::default()
arena: Default::default(),
strings: init.iter().copied().collect(),
}))
}
#[inline]
fn intern(&self, string: &str) -> Symbol {
let mut inner = self.0.lock();
if let Some(&name) = inner.names.get(string) {
return name;
if let Some(idx) = inner.strings.get_index_of(string) {
return Symbol::new(idx as u32);
}
let name = Symbol::new(inner.strings.len() as u32);
// SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
// and immediately convert the clone back to `&[u8]`, all because there
// is no `inner.arena.alloc_str()` method. This is clearly safe.
@ -2122,20 +2113,21 @@ impl Interner {
// SAFETY: we can extend the arena allocation to `'static` because we
// only access these while the arena is still alive.
let string: &'static str = unsafe { &*(string as *const str) };
inner.strings.push(string);
// This second hash table lookup can be avoided by using `RawEntryMut`,
// but this code path isn't hot enough for it to be worth it. See
// #91445 for details.
inner.names.insert(string, name);
name
let (idx, is_new) = inner.strings.insert_full(string);
debug_assert!(is_new); // due to the get_index_of check above
Symbol::new(idx as u32)
}
/// Get the symbol as a string.
///
/// [`Symbol::as_str()`] should be used in preference to this function.
fn get(&self, symbol: Symbol) -> &str {
self.0.lock().strings[symbol.0.as_usize()]
self.0.lock().strings.get_index(symbol.0.as_usize()).unwrap()
}
}

View file

@ -4,7 +4,7 @@ use crate::create_default_session_globals_then;
#[test]
fn interner_tests() {
let i = Interner::default();
let i = Interner::prefill(&[]);
// first one is zero:
assert_eq!(i.intern("dog"), Symbol::new(0));
// re-use gets the same entry:

View file

@ -119,25 +119,11 @@ impl NestedGoals<'_> {
#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
pub enum GenerateProofTree {
Yes(UseGlobalCache),
Yes,
IfEnabled,
Never,
}
#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
pub enum UseGlobalCache {
Yes,
No,
}
impl UseGlobalCache {
pub fn from_bool(use_cache: bool) -> Self {
match use_cache {
true => UseGlobalCache::Yes,
false => UseGlobalCache::No,
}
}
}
pub trait InferCtxtEvalExt<'tcx> {
/// Evaluates a goal from **outside** of the trait solver.
///

View file

@ -17,7 +17,7 @@ use rustc_middle::traits::solve::{Certainty, Goal};
use rustc_middle::ty;
use crate::solve::inspect::ProofTreeBuilder;
use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache};
use crate::solve::{GenerateProofTree, InferCtxtEvalExt};
pub struct InspectGoal<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
@ -82,8 +82,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
}
for &goal in &instantiated_goals {
let (_, proof_tree) =
infcx.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No));
let (_, proof_tree) = infcx.evaluate_root_goal(goal, GenerateProofTree::Yes);
let proof_tree = proof_tree.unwrap();
visitor.visit_goal(&InspectGoal::new(
infcx,
@ -169,11 +168,11 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
let mut candidates = vec![];
let last_eval_step = match self.evaluation.evaluation.kind {
inspect::CanonicalGoalEvaluationKind::Overflow
| inspect::CanonicalGoalEvaluationKind::CacheHit(_) => {
| inspect::CanonicalGoalEvaluationKind::CycleInStack => {
warn!("unexpected root evaluation: {:?}", self.evaluation);
return vec![];
}
inspect::CanonicalGoalEvaluationKind::Uncached { ref revisions } => {
inspect::CanonicalGoalEvaluationKind::Evaluation { ref revisions } => {
if let Some(last) = revisions.last() {
last
} else {
@ -227,8 +226,7 @@ impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> {
goal: Goal<'tcx, ty::Predicate<'tcx>>,
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
let (_, proof_tree) =
self.evaluate_root_goal(goal, GenerateProofTree::Yes(UseGlobalCache::No));
let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
let proof_tree = proof_tree.unwrap();
visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree))
}

View file

@ -3,6 +3,8 @@
//! This code is *a bit* of a mess and can hopefully be
//! mostly ignored. For a general overview of how it works,
//! see the comment on [ProofTreeBuilder].
use std::mem;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{
CanonicalInput, Certainty, Goal, IsNormalizesToHack, QueryInput, QueryResult,
@ -10,7 +12,6 @@ use rustc_middle::traits::solve::{
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::config::DumpSolverProofTree;
use crate::solve::eval_ctxt::UseGlobalCache;
use crate::solve::{self, inspect, EvalCtxt, GenerateProofTree};
/// The core data structure when building proof trees.
@ -34,12 +35,7 @@ use crate::solve::{self, inspect, EvalCtxt, GenerateProofTree};
/// is called to recursively convert the whole structure to a
/// finished proof tree.
pub(in crate::solve) struct ProofTreeBuilder<'tcx> {
state: Option<Box<BuilderData<'tcx>>>,
}
struct BuilderData<'tcx> {
tree: DebugSolver<'tcx>,
use_global_cache: UseGlobalCache,
state: Option<Box<DebugSolver<'tcx>>>,
}
/// The current state of the proof tree builder, at most places
@ -118,36 +114,46 @@ pub(in crate::solve) enum WipGoalEvaluationKind<'tcx> {
Nested { is_normalizes_to_hack: IsNormalizesToHack },
}
#[derive(Eq, PartialEq, Debug)]
pub(in crate::solve) enum WipCanonicalGoalEvaluationKind {
#[derive(Eq, PartialEq)]
pub(in crate::solve) enum WipCanonicalGoalEvaluationKind<'tcx> {
Overflow,
CacheHit(inspect::CacheHit),
CycleInStack,
Interned { revisions: &'tcx [inspect::GoalEvaluationStep<'tcx>] },
}
impl std::fmt::Debug for WipCanonicalGoalEvaluationKind<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Overflow => write!(f, "Overflow"),
Self::CycleInStack => write!(f, "CycleInStack"),
Self::Interned { revisions: _ } => f.debug_struct("Interned").finish_non_exhaustive(),
}
}
}
#[derive(Eq, PartialEq, Debug)]
struct WipCanonicalGoalEvaluation<'tcx> {
goal: CanonicalInput<'tcx>,
kind: Option<WipCanonicalGoalEvaluationKind>,
kind: Option<WipCanonicalGoalEvaluationKind<'tcx>>,
/// Only used for uncached goals. After we finished evaluating
/// the goal, this is interned and moved into `kind`.
revisions: Vec<WipGoalEvaluationStep<'tcx>>,
result: Option<QueryResult<'tcx>>,
}
impl<'tcx> WipCanonicalGoalEvaluation<'tcx> {
fn finalize(self) -> inspect::CanonicalGoalEvaluation<'tcx> {
let kind = match self.kind {
Some(WipCanonicalGoalEvaluationKind::Overflow) => {
assert!(self.revisions.is_empty());
let kind = match self.kind.unwrap() {
WipCanonicalGoalEvaluationKind::Overflow => {
inspect::CanonicalGoalEvaluationKind::Overflow
}
Some(WipCanonicalGoalEvaluationKind::CacheHit(hit)) => {
inspect::CanonicalGoalEvaluationKind::CacheHit(hit)
WipCanonicalGoalEvaluationKind::CycleInStack => {
inspect::CanonicalGoalEvaluationKind::CycleInStack
}
WipCanonicalGoalEvaluationKind::Interned { revisions } => {
inspect::CanonicalGoalEvaluationKind::Evaluation { revisions }
}
None => inspect::CanonicalGoalEvaluationKind::Uncached {
revisions: self
.revisions
.into_iter()
.map(WipGoalEvaluationStep::finalize)
.collect(),
},
};
inspect::CanonicalGoalEvaluation { goal: self.goal, kind, result: self.result.unwrap() }
@ -226,33 +232,20 @@ impl<'tcx> WipProbeStep<'tcx> {
}
impl<'tcx> ProofTreeBuilder<'tcx> {
fn new(
state: impl Into<DebugSolver<'tcx>>,
use_global_cache: UseGlobalCache,
) -> ProofTreeBuilder<'tcx> {
ProofTreeBuilder {
state: Some(Box::new(BuilderData { tree: state.into(), use_global_cache })),
}
fn new(state: impl Into<DebugSolver<'tcx>>) -> ProofTreeBuilder<'tcx> {
ProofTreeBuilder { state: Some(Box::new(state.into())) }
}
fn nested<T: Into<DebugSolver<'tcx>>>(&self, state: impl FnOnce() -> T) -> Self {
match &self.state {
Some(prev_state) => Self {
state: Some(Box::new(BuilderData {
tree: state().into(),
use_global_cache: prev_state.use_global_cache,
})),
},
None => Self { state: None },
}
ProofTreeBuilder { state: self.state.as_ref().map(|_| Box::new(state().into())) }
}
fn as_mut(&mut self) -> Option<&mut DebugSolver<'tcx>> {
self.state.as_mut().map(|boxed| &mut boxed.tree)
self.state.as_deref_mut()
}
pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> {
match self.state?.tree {
match *self.state? {
DebugSolver::GoalEvaluation(wip_goal_evaluation) => {
Some(wip_goal_evaluation.finalize())
}
@ -260,13 +253,6 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
}
pub fn use_global_cache(&self) -> bool {
self.state
.as_ref()
.map(|state| matches!(state.use_global_cache, UseGlobalCache::Yes))
.unwrap_or(true)
}
pub fn new_maybe_root(
tcx: TyCtxt<'tcx>,
generate_proof_tree: GenerateProofTree,
@ -276,10 +262,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
GenerateProofTree::IfEnabled => {
let opts = &tcx.sess.opts.unstable_opts;
match opts.dump_solver_proof_tree {
DumpSolverProofTree::Always => {
let use_cache = opts.dump_solver_proof_tree_use_cache.unwrap_or(true);
ProofTreeBuilder::new_root(UseGlobalCache::from_bool(use_cache))
}
DumpSolverProofTree::Always => ProofTreeBuilder::new_root(),
// `OnError` is handled by reevaluating goals in error
// reporting with `GenerateProofTree::Yes`.
DumpSolverProofTree::OnError | DumpSolverProofTree::Never => {
@ -287,12 +270,12 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
}
}
GenerateProofTree::Yes(use_cache) => ProofTreeBuilder::new_root(use_cache),
GenerateProofTree::Yes => ProofTreeBuilder::new_root(),
}
}
pub fn new_root(use_global_cache: UseGlobalCache) -> ProofTreeBuilder<'tcx> {
ProofTreeBuilder::new(DebugSolver::Root, use_global_cache)
pub fn new_root() -> ProofTreeBuilder<'tcx> {
ProofTreeBuilder::new(DebugSolver::Root)
}
pub fn new_noop() -> ProofTreeBuilder<'tcx> {
@ -336,9 +319,27 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
})
}
pub fn finalize_evaluation(
&mut self,
tcx: TyCtxt<'tcx>,
) -> Option<&'tcx [inspect::GoalEvaluationStep<'tcx>]> {
self.as_mut().map(|this| match this {
DebugSolver::CanonicalGoalEvaluation(evaluation) => {
let revisions = mem::take(&mut evaluation.revisions)
.into_iter()
.map(WipGoalEvaluationStep::finalize);
let revisions = &*tcx.arena.alloc_from_iter(revisions);
let kind = WipCanonicalGoalEvaluationKind::Interned { revisions };
assert_eq!(evaluation.kind.replace(kind), None);
revisions
}
_ => unreachable!(),
})
}
pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
match (this, canonical_goal_evaluation.state.unwrap().tree) {
match (this, *canonical_goal_evaluation.state.unwrap()) {
(
DebugSolver::GoalEvaluation(goal_evaluation),
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation),
@ -348,7 +349,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
}
pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind) {
pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind<'tcx>) {
if let Some(this) = self.as_mut() {
match this {
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
@ -372,7 +373,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
match (this, goal_evaluation.state.unwrap().tree) {
match (this, *goal_evaluation.state.unwrap()) {
(
DebugSolver::AddedGoalsEvaluation(WipAddedGoalsEvaluation {
evaluations, ..
@ -396,7 +397,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
match (this, goal_evaluation_step.state.unwrap().tree) {
match (this, *goal_evaluation_step.state.unwrap()) {
(
DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations),
DebugSolver::GoalEvaluationStep(goal_evaluation_step),
@ -444,7 +445,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
pub fn finish_probe(&mut self, probe: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
match (this, probe.state.unwrap().tree) {
match (this, *probe.state.unwrap()) {
(
DebugSolver::Probe(WipProbe { steps, .. })
| DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep {
@ -486,7 +487,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
pub fn added_goals_evaluation(&mut self, added_goals_evaluation: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() {
match (this, added_goals_evaluation.state.unwrap().tree) {
match (this, *added_goals_evaluation.state.unwrap()) {
(
DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep {
evaluation: WipProbe { steps, .. },

View file

@ -38,9 +38,7 @@ mod project_goals;
mod search_graph;
mod trait_goals;
pub use eval_ctxt::{
EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, UseGlobalCache,
};
pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
pub use fulfill::FulfillmentCtxt;
pub(crate) use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};

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